Athspi commited on
Commit
c140ae2
·
verified ·
1 Parent(s): fb742dc

Update templates/index.html

Browse files
Files changed (1) hide show
  1. templates/index.html +19 -213
templates/index.html CHANGED
@@ -3,13 +3,9 @@
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Object Remover AI</title>
7
- <!-- Google Fonts -->
8
  <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap" rel="stylesheet">
9
- <!-- Font Awesome -->
10
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
11
- <!-- AOS Animation -->
12
- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/aos/2.3.4/aos.css">
13
  <style>
14
  :root {
15
  --primary-color: #6366f1;
@@ -30,7 +26,6 @@
30
  margin: 0;
31
  padding: 0;
32
  min-height: 100vh;
33
- overflow-x: hidden;
34
  }
35
 
36
  .container {
@@ -42,7 +37,6 @@
42
  header {
43
  text-align: center;
44
  margin-bottom: 2rem;
45
- padding-top: 1rem;
46
  }
47
 
48
  .logo {
@@ -65,7 +59,6 @@
65
  -webkit-background-clip: text;
66
  background-clip: text;
67
  color: transparent;
68
- animation: fadeIn 1s ease-out;
69
  }
70
 
71
  .subtitle {
@@ -92,9 +85,6 @@
92
  box-shadow: 0 10px 25px rgba(0, 0, 0, 0.05);
93
  padding: 1.5rem;
94
  transition: transform 0.3s ease, box-shadow 0.3s ease;
95
- height: 100%;
96
- display: flex;
97
- flex-direction: column;
98
  }
99
 
100
  .card:hover {
@@ -102,19 +92,6 @@
102
  box-shadow: 0 15px 35px rgba(0, 0, 0, 0.1);
103
  }
104
 
105
- .card-title {
106
- font-size: 1.25rem;
107
- color: var(--primary-color);
108
- margin-bottom: 1rem;
109
- display: flex;
110
- align-items: center;
111
- gap: 0.5rem;
112
- }
113
-
114
- .card-title i {
115
- font-size: 1.5rem;
116
- }
117
-
118
  .upload-area {
119
  border: 2px dashed #d1d5db;
120
  border-radius: 0.75rem;
@@ -136,21 +113,10 @@
136
  background-color: rgba(99, 102, 241, 0.05);
137
  }
138
 
139
- .upload-area i {
140
- font-size: 3rem;
141
- color: var(--text-secondary);
142
- margin-bottom: 1rem;
143
- }
144
-
145
- .upload-area.active {
146
- border-color: var(--primary-color);
147
- }
148
-
149
  .upload-placeholder {
150
  display: flex;
151
  flex-direction: column;
152
  align-items: center;
153
- transition: opacity 0.3s ease;
154
  }
155
 
156
  .preview-container {
@@ -179,7 +145,6 @@
179
  display: block;
180
  margin-bottom: 0.5rem;
181
  font-weight: 500;
182
- color: var(--text-primary);
183
  }
184
 
185
  input[type="text"] {
@@ -221,14 +186,6 @@
221
  transform: translateY(-2px);
222
  }
223
 
224
- .button:active {
225
- transform: translateY(0);
226
- }
227
-
228
- .button i {
229
- font-size: 1.25rem;
230
- }
231
-
232
  .button:disabled {
233
  background-color: #d1d5db;
234
  cursor: not-allowed;
@@ -252,19 +209,6 @@
252
  display: none;
253
  }
254
 
255
- .result-placeholder {
256
- color: var(--text-secondary);
257
- display: flex;
258
- flex-direction: column;
259
- align-items: center;
260
- }
261
-
262
- .result-placeholder i {
263
- font-size: 3rem;
264
- margin-bottom: 1rem;
265
- color: var(--text-secondary);
266
- }
267
-
268
  .spinner {
269
  display: none;
270
  width: 40px;
@@ -281,24 +225,11 @@
281
  display: none;
282
  }
283
 
284
- .download-btn:hover {
285
- background-color: #0d9668;
286
- }
287
-
288
  .error-message {
289
  color: var(--error);
290
  margin-top: 1rem;
291
  display: none;
292
  text-align: center;
293
- font-size: 0.9rem;
294
- }
295
-
296
- footer {
297
- text-align: center;
298
- margin-top: 3rem;
299
- padding: 1.5rem;
300
- color: var(--text-secondary);
301
- font-size: 0.9rem;
302
  }
303
 
304
  @keyframes spin {
@@ -306,81 +237,21 @@
306
  transform: rotate(360deg);
307
  }
308
  }
309
-
310
- @keyframes fadeIn {
311
- from {
312
- opacity: 0;
313
- transform: translateY(10px);
314
- }
315
- to {
316
- opacity: 1;
317
- transform: translateY(0);
318
- }
319
- }
320
-
321
- .fade-in {
322
- animation: fadeIn 0.6s ease-out;
323
- }
324
-
325
- .pulse {
326
- animation: pulse 2s infinite;
327
- }
328
-
329
- @keyframes pulse {
330
- 0% {
331
- transform: scale(1);
332
- }
333
- 50% {
334
- transform: scale(1.05);
335
- }
336
- 100% {
337
- transform: scale(1);
338
- }
339
- }
340
-
341
- .notification {
342
- position: fixed;
343
- top: 20px;
344
- right: 20px;
345
- background-color: var(--success);
346
- color: white;
347
- padding: 1rem;
348
- border-radius: 0.5rem;
349
- box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
350
- display: flex;
351
- align-items: center;
352
- gap: 0.5rem;
353
- transform: translateX(150%);
354
- transition: transform 0.3s ease;
355
- z-index: 1000;
356
- }
357
-
358
- .notification.show {
359
- transform: translateX(0);
360
- }
361
-
362
- .notification.error {
363
- background-color: var(--error);
364
- }
365
  </style>
366
  </head>
367
  <body>
368
  <div class="container">
369
- <header data-aos="fade-down">
370
  <div class="logo">
371
  <i class="fas fa-magic"></i>
372
- <h1>Object Remover AI</h1>
373
  </div>
374
- <p class="subtitle">Remove unwanted objects from your images with AI magic</p>
375
  </header>
376
 
377
  <div class="app-container">
378
- <div class="card" data-aos="fade-right" data-aos-delay="100">
379
- <div class="card-title">
380
- <i class="fas fa-upload"></i>
381
- <span>Upload Image</span>
382
- </div>
383
- <div id="uploadArea" class="upload-area">
384
  <div class="upload-placeholder">
385
  <i class="fas fa-cloud-upload-alt"></i>
386
  <p>Click or drag & drop your image here</p>
@@ -393,7 +264,7 @@
393
 
394
  <div class="form-group">
395
  <label for="objectType">What do you want to remove?</label>
396
- <input type="text" id="objectType" placeholder="e.g., moon, human, text, hat, car..." value="text">
397
  </div>
398
 
399
  <button id="processBtn" class="button" disabled>
@@ -403,13 +274,9 @@
403
  <p class="error-message" id="errorMessage"></p>
404
  </div>
405
 
406
- <div class="card" data-aos="fade-left" data-aos-delay="200">
407
- <div class="card-title">
408
- <i class="fas fa-image"></i>
409
- <span>Result</span>
410
- </div>
411
  <div class="result-area">
412
- <div class="result-placeholder" id="resultPlaceholder">
413
  <i class="fas fa-image"></i>
414
  <p>Your edited image will appear here</p>
415
  </div>
@@ -422,30 +289,9 @@
422
  </a>
423
  </div>
424
  </div>
425
-
426
- <footer>
427
- <p>© 2025 Object Remover AI | Powered by Gemini API</p>
428
- </footer>
429
-
430
- <div class="notification" id="notification">
431
- <i class="fas fa-check-circle"></i>
432
- <span id="notificationText">Success!</span>
433
- </div>
434
  </div>
435
 
436
- <!-- Import AOS Animation Library -->
437
- <script src="https://cdnjs.cloudflare.com/ajax/libs/aos/2.3.4/aos.js"></script>
438
-
439
  <script>
440
- // Initialize AOS animation library
441
- document.addEventListener('DOMContentLoaded', function() {
442
- AOS.init({
443
- duration: 800,
444
- once: true
445
- });
446
- });
447
-
448
- // Elements
449
  const uploadArea = document.getElementById('uploadArea');
450
  const previewContainer = document.getElementById('previewContainer');
451
  const imagePreview = document.getElementById('imagePreview');
@@ -456,14 +302,11 @@
456
  const spinner = document.getElementById('spinner');
457
  const downloadBtn = document.getElementById('downloadBtn');
458
  const errorMessage = document.getElementById('errorMessage');
459
- const notification = document.getElementById('notification');
460
- const notificationText = document.getElementById('notificationText');
461
 
462
- // File input
463
  let selectedFile = null;
464
 
465
  // Handle file selection
466
- uploadArea.addEventListener('click', function() {
467
  const fileInput = document.createElement('input');
468
  fileInput.type = 'file';
469
  fileInput.accept = 'image/jpeg, image/png';
@@ -472,25 +315,23 @@
472
  });
473
 
474
  // Handle drag and drop
475
- uploadArea.addEventListener('dragover', function(e) {
476
  e.preventDefault();
477
  uploadArea.classList.add('active');
478
  });
479
 
480
- uploadArea.addEventListener('dragleave', function() {
481
  uploadArea.classList.remove('active');
482
  });
483
 
484
- uploadArea.addEventListener('drop', function(e) {
485
  e.preventDefault();
486
  uploadArea.classList.remove('active');
487
-
488
  if (e.dataTransfer.files.length > 0) {
489
  handleFile(e.dataTransfer.files[0]);
490
  }
491
  });
492
 
493
- // Handle file selection
494
  function handleFileSelect(e) {
495
  if (e.target.files.length > 0) {
496
  handleFile(e.target.files[0]);
@@ -498,7 +339,6 @@
498
  }
499
 
500
  function handleFile(file) {
501
- // Check if file is an image
502
  if (!file.type.match('image.*')) {
503
  showError('Please select a valid image file (JPG or PNG)');
504
  return;
@@ -507,16 +347,11 @@
507
  selectedFile = file;
508
  const reader = new FileReader();
509
 
510
- reader.onload = function(e) {
511
- // Display image preview
512
  imagePreview.src = e.target.result;
513
  previewContainer.style.display = 'flex';
514
  document.querySelector('.upload-placeholder').style.opacity = '0';
515
-
516
- // Enable process button
517
  processBtn.disabled = false;
518
-
519
- // Clear any previous errors
520
  hideError();
521
  };
522
 
@@ -524,7 +359,7 @@
524
  }
525
 
526
  // Process image
527
- processBtn.addEventListener('click', function() {
528
  if (!selectedFile) {
529
  showError('Please select an image first');
530
  return;
@@ -536,24 +371,22 @@
536
  return;
537
  }
538
 
539
- // Show loading state
540
  showLoading();
541
 
542
- // Read file as data URL
543
  const reader = new FileReader();
544
- reader.onload = function(e) {
545
  const imageData = e.target.result;
546
  processImage(imageData, objectType);
547
  };
548
  reader.readAsDataURL(selectedFile);
549
  });
550
 
551
- // Process image through API
552
  function processImage(imageData, objectType) {
553
  fetch('/process', {
554
  method: 'POST',
555
  headers: {
556
- 'Content-Type': 'application/json'
 
557
  },
558
  body: JSON.stringify({
559
  image: imageData,
@@ -563,19 +396,12 @@
563
  .then(response => response.json())
564
  .then(data => {
565
  hideLoading();
566
-
567
  if (data.success) {
568
- // Show result
569
- resultImage.src = data.resultPath + '?t=' + new Date().getTime(); // Add timestamp to prevent caching
570
  resultImage.style.display = 'block';
571
  resultPlaceholder.style.display = 'none';
572
-
573
- // Enable download button
574
  downloadBtn.style.display = 'flex';
575
  downloadBtn.href = data.resultPath;
576
-
577
- // Show success notification
578
- showNotification('Image processed successfully!', false);
579
  } else {
580
  showError(data.message || 'Failed to process image');
581
  }
@@ -587,7 +413,6 @@
587
  });
588
  }
589
 
590
- // Helper functions
591
  function showLoading() {
592
  spinner.style.display = 'block';
593
  resultPlaceholder.style.display = 'none';
@@ -604,30 +429,11 @@
604
  function showError(message) {
605
  errorMessage.textContent = message;
606
  errorMessage.style.display = 'block';
607
- showNotification(message, true);
608
  }
609
 
610
  function hideError() {
611
  errorMessage.style.display = 'none';
612
  }
613
-
614
- function showNotification(message, isError) {
615
- notificationText.textContent = message;
616
-
617
- if (isError) {
618
- notification.classList.add('error');
619
- notification.querySelector('i').className = 'fas fa-exclamation-circle';
620
- } else {
621
- notification.classList.remove('error');
622
- notification.querySelector('i').className = 'fas fa-check-circle';
623
- }
624
-
625
- notification.classList.add('show');
626
-
627
- setTimeout(() => {
628
- notification.classList.remove('show');
629
- }, 5000);
630
- }
631
  </script>
632
  </body>
633
  </html>
 
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>AI Object Remover</title>
 
7
  <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap" rel="stylesheet">
 
8
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
 
 
9
  <style>
10
  :root {
11
  --primary-color: #6366f1;
 
26
  margin: 0;
27
  padding: 0;
28
  min-height: 100vh;
 
29
  }
30
 
31
  .container {
 
37
  header {
38
  text-align: center;
39
  margin-bottom: 2rem;
 
40
  }
41
 
42
  .logo {
 
59
  -webkit-background-clip: text;
60
  background-clip: text;
61
  color: transparent;
 
62
  }
63
 
64
  .subtitle {
 
85
  box-shadow: 0 10px 25px rgba(0, 0, 0, 0.05);
86
  padding: 1.5rem;
87
  transition: transform 0.3s ease, box-shadow 0.3s ease;
 
 
 
88
  }
89
 
90
  .card:hover {
 
92
  box-shadow: 0 15px 35px rgba(0, 0, 0, 0.1);
93
  }
94
 
 
 
 
 
 
 
 
 
 
 
 
 
 
95
  .upload-area {
96
  border: 2px dashed #d1d5db;
97
  border-radius: 0.75rem;
 
113
  background-color: rgba(99, 102, 241, 0.05);
114
  }
115
 
 
 
 
 
 
 
 
 
 
 
116
  .upload-placeholder {
117
  display: flex;
118
  flex-direction: column;
119
  align-items: center;
 
120
  }
121
 
122
  .preview-container {
 
145
  display: block;
146
  margin-bottom: 0.5rem;
147
  font-weight: 500;
 
148
  }
149
 
150
  input[type="text"] {
 
186
  transform: translateY(-2px);
187
  }
188
 
 
 
 
 
 
 
 
 
189
  .button:disabled {
190
  background-color: #d1d5db;
191
  cursor: not-allowed;
 
209
  display: none;
210
  }
211
 
 
 
 
 
 
 
 
 
 
 
 
 
 
212
  .spinner {
213
  display: none;
214
  width: 40px;
 
225
  display: none;
226
  }
227
 
 
 
 
 
228
  .error-message {
229
  color: var(--error);
230
  margin-top: 1rem;
231
  display: none;
232
  text-align: center;
 
 
 
 
 
 
 
 
 
233
  }
234
 
235
  @keyframes spin {
 
237
  transform: rotate(360deg);
238
  }
239
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
240
  </style>
241
  </head>
242
  <body>
243
  <div class="container">
244
+ <header>
245
  <div class="logo">
246
  <i class="fas fa-magic"></i>
247
+ <h1>AI Object Remover</h1>
248
  </div>
249
+ <p class="subtitle">Remove unwanted objects from your images with AI</p>
250
  </header>
251
 
252
  <div class="app-container">
253
+ <div class="card">
254
+ <div class="upload-area" id="uploadArea">
 
 
 
 
255
  <div class="upload-placeholder">
256
  <i class="fas fa-cloud-upload-alt"></i>
257
  <p>Click or drag & drop your image here</p>
 
264
 
265
  <div class="form-group">
266
  <label for="objectType">What do you want to remove?</label>
267
+ <input type="text" id="objectType" placeholder="e.g., person, text, car..." value="text">
268
  </div>
269
 
270
  <button id="processBtn" class="button" disabled>
 
274
  <p class="error-message" id="errorMessage"></p>
275
  </div>
276
 
277
+ <div class="card">
 
 
 
 
278
  <div class="result-area">
279
+ <div id="resultPlaceholder">
280
  <i class="fas fa-image"></i>
281
  <p>Your edited image will appear here</p>
282
  </div>
 
289
  </a>
290
  </div>
291
  </div>
 
 
 
 
 
 
 
 
 
292
  </div>
293
 
 
 
 
294
  <script>
 
 
 
 
 
 
 
 
 
295
  const uploadArea = document.getElementById('uploadArea');
296
  const previewContainer = document.getElementById('previewContainer');
297
  const imagePreview = document.getElementById('imagePreview');
 
302
  const spinner = document.getElementById('spinner');
303
  const downloadBtn = document.getElementById('downloadBtn');
304
  const errorMessage = document.getElementById('errorMessage');
 
 
305
 
 
306
  let selectedFile = null;
307
 
308
  // Handle file selection
309
+ uploadArea.addEventListener('click', () => {
310
  const fileInput = document.createElement('input');
311
  fileInput.type = 'file';
312
  fileInput.accept = 'image/jpeg, image/png';
 
315
  });
316
 
317
  // Handle drag and drop
318
+ uploadArea.addEventListener('dragover', (e) => {
319
  e.preventDefault();
320
  uploadArea.classList.add('active');
321
  });
322
 
323
+ uploadArea.addEventListener('dragleave', () => {
324
  uploadArea.classList.remove('active');
325
  });
326
 
327
+ uploadArea.addEventListener('drop', (e) => {
328
  e.preventDefault();
329
  uploadArea.classList.remove('active');
 
330
  if (e.dataTransfer.files.length > 0) {
331
  handleFile(e.dataTransfer.files[0]);
332
  }
333
  });
334
 
 
335
  function handleFileSelect(e) {
336
  if (e.target.files.length > 0) {
337
  handleFile(e.target.files[0]);
 
339
  }
340
 
341
  function handleFile(file) {
 
342
  if (!file.type.match('image.*')) {
343
  showError('Please select a valid image file (JPG or PNG)');
344
  return;
 
347
  selectedFile = file;
348
  const reader = new FileReader();
349
 
350
+ reader.onload = (e) => {
 
351
  imagePreview.src = e.target.result;
352
  previewContainer.style.display = 'flex';
353
  document.querySelector('.upload-placeholder').style.opacity = '0';
 
 
354
  processBtn.disabled = false;
 
 
355
  hideError();
356
  };
357
 
 
359
  }
360
 
361
  // Process image
362
+ processBtn.addEventListener('click', () => {
363
  if (!selectedFile) {
364
  showError('Please select an image first');
365
  return;
 
371
  return;
372
  }
373
 
 
374
  showLoading();
375
 
 
376
  const reader = new FileReader();
377
+ reader.onload = (e) => {
378
  const imageData = e.target.result;
379
  processImage(imageData, objectType);
380
  };
381
  reader.readAsDataURL(selectedFile);
382
  });
383
 
 
384
  function processImage(imageData, objectType) {
385
  fetch('/process', {
386
  method: 'POST',
387
  headers: {
388
+ 'Content-Type': 'application/json',
389
+ 'X-Requested-With': 'XMLHttpRequest'
390
  },
391
  body: JSON.stringify({
392
  image: imageData,
 
396
  .then(response => response.json())
397
  .then(data => {
398
  hideLoading();
 
399
  if (data.success) {
400
+ resultImage.src = data.resultPath + '?t=' + new Date().getTime();
 
401
  resultImage.style.display = 'block';
402
  resultPlaceholder.style.display = 'none';
 
 
403
  downloadBtn.style.display = 'flex';
404
  downloadBtn.href = data.resultPath;
 
 
 
405
  } else {
406
  showError(data.message || 'Failed to process image');
407
  }
 
413
  });
414
  }
415
 
 
416
  function showLoading() {
417
  spinner.style.display = 'block';
418
  resultPlaceholder.style.display = 'none';
 
429
  function showError(message) {
430
  errorMessage.textContent = message;
431
  errorMessage.style.display = 'block';
 
432
  }
433
 
434
  function hideError() {
435
  errorMessage.style.display = 'none';
436
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
437
  </script>
438
  </body>
439
  </html>