Athspi commited on
Commit
063cc44
·
verified ·
1 Parent(s): 5103db2

Create templates/index.html

Browse files
Files changed (1) hide show
  1. templates/index.html +633 -0
templates/index.html ADDED
@@ -0,0 +1,633 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
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;
16
+ --secondary-color: #4f46e5;
17
+ --accent-color: #8b5cf6;
18
+ --background: #f8fafc;
19
+ --card-bg: #ffffff;
20
+ --text-primary: #1e293b;
21
+ --text-secondary: #64748b;
22
+ --success: #10b981;
23
+ --error: #ef4444;
24
+ }
25
+
26
+ body {
27
+ font-family: 'Poppins', sans-serif;
28
+ background-color: var(--background);
29
+ color: var(--text-primary);
30
+ margin: 0;
31
+ padding: 0;
32
+ min-height: 100vh;
33
+ overflow-x: hidden;
34
+ }
35
+
36
+ .container {
37
+ max-width: 1200px;
38
+ margin: 0 auto;
39
+ padding: 2rem;
40
+ }
41
+
42
+ header {
43
+ text-align: center;
44
+ margin-bottom: 2rem;
45
+ padding-top: 1rem;
46
+ }
47
+
48
+ .logo {
49
+ display: flex;
50
+ align-items: center;
51
+ justify-content: center;
52
+ gap: 1rem;
53
+ margin-bottom: 1rem;
54
+ }
55
+
56
+ .logo i {
57
+ font-size: 2.5rem;
58
+ color: var(--primary-color);
59
+ }
60
+
61
+ h1 {
62
+ font-size: 2.5rem;
63
+ margin: 0;
64
+ background: linear-gradient(to right, var(--primary-color), var(--accent-color));
65
+ -webkit-background-clip: text;
66
+ background-clip: text;
67
+ color: transparent;
68
+ animation: fadeIn 1s ease-out;
69
+ }
70
+
71
+ .subtitle {
72
+ color: var(--text-secondary);
73
+ margin-top: 0.5rem;
74
+ font-weight: 400;
75
+ }
76
+
77
+ .app-container {
78
+ display: grid;
79
+ grid-template-columns: 1fr 1fr;
80
+ gap: 2rem;
81
+ }
82
+
83
+ @media (max-width: 768px) {
84
+ .app-container {
85
+ grid-template-columns: 1fr;
86
+ }
87
+ }
88
+
89
+ .card {
90
+ background-color: var(--card-bg);
91
+ border-radius: 1rem;
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 {
101
+ transform: translateY(-5px);
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;
121
+ padding: 2rem;
122
+ text-align: center;
123
+ cursor: pointer;
124
+ transition: all 0.3s ease;
125
+ margin-bottom: 1rem;
126
+ position: relative;
127
+ min-height: 200px;
128
+ display: flex;
129
+ align-items: center;
130
+ justify-content: center;
131
+ overflow: hidden;
132
+ }
133
+
134
+ .upload-area:hover {
135
+ border-color: var(--primary-color);
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 {
157
+ position: absolute;
158
+ top: 0;
159
+ left: 0;
160
+ width: 100%;
161
+ height: 100%;
162
+ display: none;
163
+ align-items: center;
164
+ justify-content: center;
165
+ background-color: var(--card-bg);
166
+ }
167
+
168
+ .preview-container img {
169
+ max-width: 100%;
170
+ max-height: 100%;
171
+ object-fit: contain;
172
+ }
173
+
174
+ .form-group {
175
+ margin-bottom: 1.5rem;
176
+ }
177
+
178
+ label {
179
+ display: block;
180
+ margin-bottom: 0.5rem;
181
+ font-weight: 500;
182
+ color: var(--text-primary);
183
+ }
184
+
185
+ input[type="text"] {
186
+ width: 100%;
187
+ padding: 0.75rem 1rem;
188
+ border-radius: 0.5rem;
189
+ border: 1px solid #d1d5db;
190
+ font-family: inherit;
191
+ font-size: 1rem;
192
+ transition: border-color 0.3s ease, box-shadow 0.3s ease;
193
+ }
194
+
195
+ input[type="text"]:focus {
196
+ outline: none;
197
+ border-color: var(--primary-color);
198
+ box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.2);
199
+ }
200
+
201
+ .button {
202
+ background-color: var(--primary-color);
203
+ color: white;
204
+ border: none;
205
+ border-radius: 0.5rem;
206
+ padding: 0.75rem 1.5rem;
207
+ font-family: inherit;
208
+ font-size: 1rem;
209
+ font-weight: 500;
210
+ cursor: pointer;
211
+ transition: background-color 0.3s ease, transform 0.2s ease;
212
+ display: flex;
213
+ align-items: center;
214
+ justify-content: center;
215
+ gap: 0.5rem;
216
+ width: 100%;
217
+ }
218
+
219
+ .button:hover {
220
+ background-color: var(--secondary-color);
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;
235
+ }
236
+
237
+ .result-area {
238
+ display: flex;
239
+ flex-direction: column;
240
+ align-items: center;
241
+ justify-content: center;
242
+ text-align: center;
243
+ min-height: 200px;
244
+ position: relative;
245
+ }
246
+
247
+ .result-image {
248
+ max-width: 100%;
249
+ max-height: 300px;
250
+ border-radius: 0.5rem;
251
+ box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
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;
271
+ height: 40px;
272
+ border: 4px solid rgba(99, 102, 241, 0.1);
273
+ border-left-color: var(--primary-color);
274
+ border-radius: 50%;
275
+ animation: spin 1s linear infinite;
276
+ }
277
+
278
+ .download-btn {
279
+ margin-top: 1rem;
280
+ background-color: var(--success);
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 {
305
+ to {
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>
387
+ <span style="font-size: 0.85rem; color: var(--text-secondary);">Supported formats: JPG, PNG</span>
388
+ </div>
389
+ <div class="preview-container" id="previewContainer">
390
+ <img id="imagePreview" src="#" alt="Preview">
391
+ </div>
392
+ </div>
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>
400
+ <i class="fas fa-wand-magic-sparkles"></i>
401
+ <span>Remove Object</span>
402
+ </button>
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>
416
+ <div class="spinner" id="spinner"></div>
417
+ <img id="resultImage" class="result-image" src="#" alt="Result">
418
+ </div>
419
+ <a id="downloadBtn" class="button download-btn" download="edited-image.png">
420
+ <i class="fas fa-download"></i>
421
+ <span>Download Image</span>
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');
452
+ const objectTypeInput = document.getElementById('objectType');
453
+ const processBtn = document.getElementById('processBtn');
454
+ const resultPlaceholder = document.getElementById('resultPlaceholder');
455
+ const resultImage = document.getElementById('resultImage');
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';
470
+ fileInput.onchange = handleFileSelect;
471
+ fileInput.click();
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]);
497
+ }
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;
505
+ }
506
+
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
+
523
+ reader.readAsDataURL(file);
524
+ }
525
+
526
+ // Process image
527
+ processBtn.addEventListener('click', function() {
528
+ if (!selectedFile) {
529
+ showError('Please select an image first');
530
+ return;
531
+ }
532
+
533
+ const objectType = objectTypeInput.value.trim();
534
+ if (!objectType) {
535
+ showError('Please specify what you want to remove');
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,
560
+ objectType: objectType
561
+ })
562
+ })
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
+ }
582
+ })
583
+ .catch(error => {
584
+ hideLoading();
585
+ showError('Error processing image. Please try again.');
586
+ console.error('Error:', error);
587
+ });
588
+ }
589
+
590
+ // Helper functions
591
+ function showLoading() {
592
+ spinner.style.display = 'block';
593
+ resultPlaceholder.style.display = 'none';
594
+ resultImage.style.display = 'none';
595
+ downloadBtn.style.display = 'none';
596
+ processBtn.disabled = true;
597
+ }
598
+
599
+ function hideLoading() {
600
+ spinner.style.display = 'none';
601
+ processBtn.disabled = false;
602
+ }
603
+
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>