bibibi12345 commited on
Commit
ed0fd8a
·
1 Parent(s): 19bbe02

added animation frontend

Browse files
Files changed (1) hide show
  1. index.html +254 -53
index.html CHANGED
@@ -113,6 +113,59 @@
113
  margin-top: 20px;
114
  display: none;
115
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
116
  </style>
117
  </head>
118
  <body>
@@ -125,8 +178,18 @@
125
  </div>
126
 
127
  <div class="input-group">
128
- <label for="prompt">Image Prompt:</label>
129
- <textarea id="prompt" placeholder="Describe the image you want to generate..."></textarea>
 
 
 
 
 
 
 
 
 
 
130
  </div>
131
 
132
  <button onclick="generateImage()">Generate Image</button>
@@ -145,8 +208,96 @@
145
  </div>
146
  </div>
147
 
148
- <script src="https://cdnjs.cloudflare.com/ajax/libs/gif.js/0.2.0/gif.min.js"></script>
149
  <script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
150
  async function generateImage() {
151
  const apiKey = document.getElementById('apiKey').value.trim();
152
  const prompt = document.getElementById('prompt').value.trim();
@@ -156,8 +307,9 @@
156
  return;
157
  }
158
 
159
- if (!prompt) {
160
- showError('Please enter a prompt');
 
161
  return;
162
  }
163
 
@@ -168,6 +320,32 @@
168
  document.querySelector('button').disabled = true;
169
 
170
  try {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
171
  const response = await fetch('/v1beta/models/gemini-2.5-flash-image-preview:generateContent', {
172
  method: 'POST',
173
  headers: {
@@ -177,9 +355,7 @@
177
  body: JSON.stringify({
178
  contents: [{
179
  role: "user",
180
- parts: [{
181
- text: prompt
182
- }]
183
  }]
184
  })
185
  });
@@ -241,8 +417,13 @@
241
  img.alt = 'Generated image';
242
  imageContainerDiv.appendChild(img);
243
  } else if (imageParts.length > 1) {
244
- // Multiple images - create animated GIF
245
- createAnimatedGif(imageParts, imageContainerDiv);
 
 
 
 
 
246
  }
247
 
248
  resultDiv.style.display = 'block';
@@ -252,52 +433,72 @@
252
  }
253
 
254
  function createAnimatedGif(imageDataArray, container) {
255
- const gif = new GIF({
256
- workers: 2,
257
- quality: 10,
258
- width: 512,
259
- height: 512
260
- });
261
-
262
- let loadedImages = 0;
263
- const totalImages = imageDataArray.length;
264
-
265
- // Show loading message for GIF creation
266
- container.innerHTML = '<p>Creating animated GIF...</p>';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
267
 
268
  imageDataArray.forEach((imageData, index) => {
269
- const img = new Image();
270
- img.onload = function() {
271
- // Create a canvas to resize the image
272
- const canvas = document.createElement('canvas');
273
- const ctx = canvas.getContext('2d');
274
- canvas.width = 512;
275
- canvas.height = 512;
276
-
277
- // Draw and resize image
278
- ctx.drawImage(img, 0, 0, 512, 512);
279
-
280
- // Add frame to GIF with 500ms delay
281
- gif.addFrame(canvas, {delay: 500});
282
-
283
- loadedImages++;
284
- if (loadedImages === totalImages) {
285
- // All images loaded, render GIF
286
- gif.on('finished', function(blob) {
287
- const url = URL.createObjectURL(blob);
288
- const gifImg = document.createElement('img');
289
- gifImg.src = url;
290
- gifImg.className = 'generated-image';
291
- gifImg.alt = 'Generated animated GIF';
292
-
293
- container.innerHTML = '';
294
- container.appendChild(gifImg);
295
- });
296
-
297
- gif.render();
298
- }
299
- };
300
  img.src = `data:image/png;base64,${imageData}`;
 
 
 
 
 
301
  });
302
  }
303
 
 
113
  margin-top: 20px;
114
  display: none;
115
  }
116
+ .file-upload {
117
+ border: 2px dashed #ddd;
118
+ border-radius: 5px;
119
+ padding: 20px;
120
+ text-align: center;
121
+ margin-bottom: 10px;
122
+ cursor: pointer;
123
+ transition: border-color 0.3s;
124
+ }
125
+ .file-upload:hover {
126
+ border-color: #4CAF50;
127
+ }
128
+ .file-upload.dragover {
129
+ border-color: #4CAF50;
130
+ background-color: #f0f8f0;
131
+ }
132
+ .uploaded-images {
133
+ display: flex;
134
+ flex-wrap: wrap;
135
+ gap: 10px;
136
+ margin-top: 10px;
137
+ }
138
+ .uploaded-image {
139
+ position: relative;
140
+ width: 100px;
141
+ height: 100px;
142
+ }
143
+ .uploaded-image img {
144
+ width: 100%;
145
+ height: 100%;
146
+ object-fit: cover;
147
+ border-radius: 5px;
148
+ border: 2px solid #ddd;
149
+ }
150
+ .remove-image {
151
+ position: absolute;
152
+ top: -5px;
153
+ right: -5px;
154
+ background: #ff4444;
155
+ color: white;
156
+ border: none;
157
+ border-radius: 50%;
158
+ width: 20px;
159
+ height: 20px;
160
+ cursor: pointer;
161
+ font-size: 12px;
162
+ display: flex;
163
+ align-items: center;
164
+ justify-content: center;
165
+ }
166
+ .remove-image:hover {
167
+ background: #cc0000;
168
+ }
169
  </style>
170
  </head>
171
  <body>
 
178
  </div>
179
 
180
  <div class="input-group">
181
+ <label for="imageUpload">Upload Images (optional):</label>
182
+ <div class="file-upload" id="fileUpload" onclick="document.getElementById('imageUpload').click()">
183
+ <p>Click here or drag and drop images to upload</p>
184
+ <p style="font-size: 12px; color: #666;">Supports: JPG, PNG, GIF, WebP</p>
185
+ </div>
186
+ <input type="file" id="imageUpload" multiple accept="image/*" style="display: none;">
187
+ <div class="uploaded-images" id="uploadedImages"></div>
188
+ </div>
189
+
190
+ <div class="input-group">
191
+ <label for="prompt">Text Prompt:</label>
192
+ <textarea id="prompt" placeholder="Describe what you want to do with the images or generate..."></textarea>
193
  </div>
194
 
195
  <button onclick="generateImage()">Generate Image</button>
 
208
  </div>
209
  </div>
210
 
 
211
  <script>
212
+ // Simple fallback for GIF creation if the library fails to load
213
+ let GIF_LIBRARY_LOADED = false;
214
+
215
+ // Try to load gif.js library
216
+ const script = document.createElement('script');
217
+ script.src = 'https://cdn.jsdelivr.net/npm/gif.js@0.2.0/dist/gif.min.js';
218
+ script.onload = function() {
219
+ GIF_LIBRARY_LOADED = true;
220
+ };
221
+ script.onerror = function() {
222
+ console.warn('GIF library failed to load, will show images individually');
223
+ };
224
+ document.head.appendChild(script);
225
+
226
+ // Global variable to store uploaded images
227
+ let uploadedImages = [];
228
+
229
+ // File upload handling
230
+ document.getElementById('imageUpload').addEventListener('change', handleFileSelect);
231
+
232
+ const fileUpload = document.getElementById('fileUpload');
233
+ fileUpload.addEventListener('dragover', handleDragOver);
234
+ fileUpload.addEventListener('drop', handleDrop);
235
+ fileUpload.addEventListener('dragleave', handleDragLeave);
236
+
237
+ function handleFileSelect(event) {
238
+ const files = Array.from(event.target.files);
239
+ processFiles(files);
240
+ }
241
+
242
+ function handleDragOver(event) {
243
+ event.preventDefault();
244
+ fileUpload.classList.add('dragover');
245
+ }
246
+
247
+ function handleDrop(event) {
248
+ event.preventDefault();
249
+ fileUpload.classList.remove('dragover');
250
+ const files = Array.from(event.dataTransfer.files);
251
+ processFiles(files);
252
+ }
253
+
254
+ function handleDragLeave(event) {
255
+ event.preventDefault();
256
+ fileUpload.classList.remove('dragover');
257
+ }
258
+
259
+ function processFiles(files) {
260
+ files.forEach(file => {
261
+ if (file.type.startsWith('image/')) {
262
+ const reader = new FileReader();
263
+ reader.onload = function(e) {
264
+ const imageData = {
265
+ name: file.name,
266
+ data: e.target.result.split(',')[1], // Remove data:image/...;base64, prefix
267
+ mimeType: file.type
268
+ };
269
+ uploadedImages.push(imageData);
270
+ displayUploadedImage(imageData, uploadedImages.length - 1);
271
+ };
272
+ reader.readAsDataURL(file);
273
+ }
274
+ });
275
+ }
276
+
277
+ function displayUploadedImage(imageData, index) {
278
+ const container = document.getElementById('uploadedImages');
279
+ const imageDiv = document.createElement('div');
280
+ imageDiv.className = 'uploaded-image';
281
+ imageDiv.innerHTML = `
282
+ <img src="data:${imageData.mimeType};base64,${imageData.data}" alt="${imageData.name}">
283
+ <button class="remove-image" onclick="removeImage(${index})">×</button>
284
+ `;
285
+ container.appendChild(imageDiv);
286
+ }
287
+
288
+ function removeImage(index) {
289
+ uploadedImages.splice(index, 1);
290
+ refreshUploadedImages();
291
+ }
292
+
293
+ function refreshUploadedImages() {
294
+ const container = document.getElementById('uploadedImages');
295
+ container.innerHTML = '';
296
+ uploadedImages.forEach((imageData, index) => {
297
+ displayUploadedImage(imageData, index);
298
+ });
299
+ }
300
+
301
  async function generateImage() {
302
  const apiKey = document.getElementById('apiKey').value.trim();
303
  const prompt = document.getElementById('prompt').value.trim();
 
307
  return;
308
  }
309
 
310
+ // Check if we have either a prompt or uploaded images
311
+ if (!prompt && uploadedImages.length === 0) {
312
+ showError('Please enter a prompt or upload at least one image');
313
  return;
314
  }
315
 
 
320
  document.querySelector('button').disabled = true;
321
 
322
  try {
323
+ // Build the parts array with text and images
324
+ const parts = [];
325
+
326
+ // Add text prompt
327
+ if (prompt) {
328
+ parts.push({
329
+ text: prompt
330
+ });
331
+ }
332
+
333
+ // Add uploaded images
334
+ uploadedImages.forEach(imageData => {
335
+ parts.push({
336
+ inlineData: {
337
+ mimeType: imageData.mimeType,
338
+ data: imageData.data
339
+ }
340
+ });
341
+ });
342
+
343
+ // Ensure we have at least some content
344
+ if (parts.length === 0) {
345
+ showError('Please enter a prompt or upload at least one image');
346
+ return;
347
+ }
348
+
349
  const response = await fetch('/v1beta/models/gemini-2.5-flash-image-preview:generateContent', {
350
  method: 'POST',
351
  headers: {
 
355
  body: JSON.stringify({
356
  contents: [{
357
  role: "user",
358
+ parts: parts
 
 
359
  }]
360
  })
361
  });
 
417
  img.alt = 'Generated image';
418
  imageContainerDiv.appendChild(img);
419
  } else if (imageParts.length > 1) {
420
+ // Multiple images - try to create animated GIF or show individually
421
+ if (GIF_LIBRARY_LOADED && typeof GIF !== 'undefined') {
422
+ createAnimatedGif(imageParts, imageContainerDiv);
423
+ } else {
424
+ // Fallback: show all images individually
425
+ showMultipleImages(imageParts, imageContainerDiv);
426
+ }
427
  }
428
 
429
  resultDiv.style.display = 'block';
 
433
  }
434
 
435
  function createAnimatedGif(imageDataArray, container) {
436
+ try {
437
+ const gif = new GIF({
438
+ workers: 2,
439
+ quality: 10,
440
+ width: 512,
441
+ height: 512
442
+ });
443
+
444
+ let loadedImages = 0;
445
+ const totalImages = imageDataArray.length;
446
+
447
+ // Show loading message for GIF creation
448
+ container.innerHTML = '<p>Creating animated GIF...</p>';
449
+
450
+ imageDataArray.forEach((imageData, index) => {
451
+ const img = new Image();
452
+ img.onload = function() {
453
+ // Create a canvas to resize the image
454
+ const canvas = document.createElement('canvas');
455
+ const ctx = canvas.getContext('2d');
456
+ canvas.width = 512;
457
+ canvas.height = 512;
458
+
459
+ // Draw and resize image
460
+ ctx.drawImage(img, 0, 0, 512, 512);
461
+
462
+ // Add frame to GIF with 500ms delay
463
+ gif.addFrame(canvas, {delay: 500});
464
+
465
+ loadedImages++;
466
+ if (loadedImages === totalImages) {
467
+ // All images loaded, render GIF
468
+ gif.on('finished', function(blob) {
469
+ const url = URL.createObjectURL(blob);
470
+ const gifImg = document.createElement('img');
471
+ gifImg.src = url;
472
+ gifImg.className = 'generated-image';
473
+ gifImg.alt = 'Generated animated GIF';
474
+
475
+ container.innerHTML = '';
476
+ container.appendChild(gifImg);
477
+ });
478
+
479
+ gif.render();
480
+ }
481
+ };
482
+ img.src = `data:image/png;base64,${imageData}`;
483
+ });
484
+ } catch (error) {
485
+ console.error('Error creating GIF:', error);
486
+ // Fallback to showing individual images
487
+ showMultipleImages(imageDataArray, container);
488
+ }
489
+ }
490
+
491
+ function showMultipleImages(imageDataArray, container) {
492
+ container.innerHTML = '<p>Multiple images generated:</p>';
493
 
494
  imageDataArray.forEach((imageData, index) => {
495
+ const img = document.createElement('img');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
496
  img.src = `data:image/png;base64,${imageData}`;
497
+ img.className = 'generated-image';
498
+ img.alt = `Generated image ${index + 1}`;
499
+ img.style.marginBottom = '10px';
500
+ img.style.display = 'block';
501
+ container.appendChild(img);
502
  });
503
  }
504