| |
|
| | |
| | function openImageEditor(imageSrc) { |
| | const editor = document.querySelector('custom-image-editor'); |
| | if (editor) { |
| | editor.style.display = 'flex'; |
| | |
| | } |
| | } |
| | function generateFaceSwap() { |
| | const resultsContainer = document.getElementById('results-container'); |
| | const selectedImages = document.querySelectorAll('#image-preview img'); |
| | const faceSelection = document.querySelectorAll('#face-selection .ring-purple-600'); |
| | |
| | if (selectedImages.length < 2) { |
| | alert('Please upload at least 2 images for face swapping'); |
| | return; |
| | } |
| |
|
| | if (faceSelection.length < 2) { |
| | alert('Please select at least 2 faces to swap'); |
| | return; |
| | } |
| |
|
| | |
| | resultsContainer.innerHTML = ` |
| | <div class="col-span-4 text-center py-12"> |
| | <div class="animate-spin rounded-full h-12 w-12 border-b-2 border-purple-600 mx-auto mb-4"></div> |
| | <p>Generating face swaps...</p> |
| | </div> |
| | `; |
| |
|
| | |
| | const sourceImages = Array.from(selectedImages).map(img => img.src); |
| |
|
| | |
| | setTimeout(() => { |
| | |
| | resultsContainer.innerHTML = ''; |
| | |
| | |
| | const selectedFaceIds = Array.from(faceSelection).map(face => face.dataset.faceId); |
| | |
| | |
| | for (let i = 0; i < 4; i++) { |
| | const resultItem = document.createElement('div'); |
| | resultItem.className = 'bg-white rounded-xl shadow-md overflow-hidden group'; |
| | |
| | |
| | const faceId1 = selectedFaceIds[0]; |
| | const faceId2 = selectedFaceIds[i % selectedFaceIds.length] || selectedFaceIds[1]; |
| | |
| | |
| | const seed = (sourceImages.join('').length + parseInt(faceId1) + parseInt(faceId2)) % 1000; |
| | |
| | resultItem.innerHTML = ` |
| | <img src="http://static.photos/people/640x360/${seed}" |
| | class="w-full h-full object-cover transition group-hover:scale-105 cursor-pointer" |
| | alt="Face swap result ${i+1}" |
| | onclick="openImageEditor(this.src)"> |
| | <div class="p-3"> |
| | <h3 class="font-semibold">Result #${i+1}</h3> |
| | <div class="flex justify-between items-center mt-2"> |
| | <button class="text-purple-600 hover:text-purple-800 text-sm flex items-center" onclick="downloadImage(this)"> |
| | <i data-feather="download" class="w-4 h-4 mr-1"></i> |
| | Download |
| | </button> |
| | <button class="text-purple-600 hover:text-purple-800 text-sm flex items-center" onclick="openImageEditor(this.parentElement.parentElement.querySelector('img').src)"> |
| | <i data-feather="edit" class="w-4 h-4 mr-1"></i> |
| | Edit |
| | </button> |
| | </div> |
| | </div> |
| | `; |
| | resultsContainer.appendChild(resultItem); |
| | } |
| | |
| | if (typeof feather !== 'undefined') { |
| | feather.replace(); |
| | } |
| | }, 2000); |
| | } |
| |
|
| | function downloadImage(button) { |
| | const img = button.closest('div').querySelector('img'); |
| | const link = document.createElement('a'); |
| | link.href = img.src; |
| | link.download = `face-swap-${Date.now()}.jpg`; |
| | document.body.appendChild(link); |
| | link.click(); |
| | document.body.removeChild(link); |
| | } |
| | document.addEventListener('DOMContentLoaded', function() { |
| | |
| | if (typeof feather !== 'undefined') { |
| | feather.replace(); |
| | } |
| |
|
| | |
| | const generateBtn = document.querySelector('main button:has(i[data-feather="refresh-cw"])'); |
| | if (generateBtn) { |
| | generateBtn.addEventListener('click', function(e) { |
| | e.preventDefault(); |
| | generateFaceSwap(); |
| | }); |
| | } |
| |
|
| | |
| | document.addEventListener('click', function(e) { |
| | if (e.target.closest('#image-preview img')) { |
| | const imgSrc = e.target.src; |
| | |
| | console.log('Image clicked for face detection:', imgSrc); |
| | } |
| | }); |
| | |
| | const faceSelection = document.getElementById('face-selection'); |
| | |
| | |
| | const fileInput = document.getElementById('file-input'); |
| | if (fileInput) { |
| | fileInput.addEventListener('change', function() { |
| | const mockFaces = []; |
| | const numFaces = Math.floor(Math.random() * 4) + 1; |
| | |
| | for (let i = 1; i <= numFaces; i++) { |
| | const colors = ['bg-red-400', 'bg-blue-400', 'bg-green-400', 'bg-yellow-400']; |
| | mockFaces.push({ |
| | id: i, |
| | name: `Face ${i}`, |
| | color: colors[i % colors.length] |
| | }); |
| | } |
| | |
| | |
| | faceSelection.innerHTML = ''; |
| | |
| | mockFaces.forEach(face => { |
| | const faceElement = document.createElement('div'); |
| | faceElement.className = `flex items-center justify-center w-16 h-16 rounded-full ${face.color} text-white cursor-pointer hover:opacity-80 transition`; |
| | faceElement.textContent = face.name; |
| | faceElement.dataset.faceId = face.id; |
| | faceElement.addEventListener('click', function() { |
| | this.classList.toggle('ring-2'); |
| | this.classList.toggle('ring-purple-600'); |
| | }); |
| | faceSelection.appendChild(faceElement); |
| | }); |
| | }); |
| | } |
| | |
| | faceSelection.innerHTML = ''; |
| | mockFaces.forEach(face => { |
| | const faceElement = document.createElement('div'); |
| | faceElement.className = `flex items-center justify-center w-16 h-16 rounded-full ${face.color} text-white cursor-pointer hover:opacity-80 transition`; |
| | faceElement.textContent = face.name; |
| | faceElement.dataset.faceId = face.id; |
| | faceElement.addEventListener('click', function() { |
| | this.classList.toggle('ring-2'); |
| | this.classList.toggle('ring-purple-600'); |
| | }); |
| | faceSelection.appendChild(faceElement); |
| | }); |
| | |
| | |
| | const fileInput = document.getElementById('file-input'); |
| | if (fileInput) { |
| | fileInput.addEventListener('change', function() { |
| | const resultsContainer = document.getElementById('results-container'); |
| | if (resultsContainer) { |
| | resultsContainer.innerHTML = ` |
| | <div class="text-center text-gray-500 py-12 col-span-4"> |
| | <i data-feather="image" class="w-12 h-12 mx-auto mb-2"></i> |
| | <p>Your face swaps will appear here</p> |
| | </div> |
| | `; |
| | if (typeof feather !== 'undefined') { |
| | feather.replace(); |
| | } |
| | } |
| | }); |
| | } |
| | |
| | const uploadArea = document.getElementById('upload-area'); |
| | const fileInput = document.getElementById('file-input'); |
| | const imagePreview = document.getElementById('image-preview'); |
| | |
| | |
| | fileInput.addEventListener('change', function(e) { |
| | handleFiles(e.target.files); |
| | }); |
| | |
| | |
| | uploadArea.addEventListener('dragover', function(e) { |
| | e.preventDefault(); |
| | uploadArea.classList.add('border-purple-500', 'bg-purple-50'); |
| | }); |
| | |
| | uploadArea.addEventListener('dragleave', function() { |
| | uploadArea.classList.remove('border-purple-500', 'bg-purple-50'); |
| | }); |
| | |
| | uploadArea.addEventListener('drop', function(e) { |
| | e.preventDefault(); |
| | uploadArea.classList.remove('border-purple-500', 'bg-purple-50'); |
| | if (e.dataTransfer.files.length) { |
| | handleFiles(e.dataTransfer.files); |
| | } |
| | }); |
| | function handleFiles(files) { |
| | |
| | Array.from(files).forEach(file => { |
| | if (!file.type.match('image.*')) return; |
| | |
| | const reader = new FileReader(); |
| | reader.onload = function(e) { |
| | |
| | const container = document.createElement('div'); |
| | container.className = 'relative group'; |
| | |
| | |
| | const img = document.createElement('img'); |
| | img.src = e.target.result; |
| | img.alt = file.name; |
| | img.className = 'w-full h-full object-cover rounded-lg'; |
| | |
| | |
| | const removeBtn = document.createElement('button'); |
| | removeBtn.className = 'absolute top-2 right-2 bg-red-500 text-white rounded-full p-1 opacity-0 group-hover:opacity-100 transition-opacity'; |
| | removeBtn.innerHTML = '<i data-feather="x"></i>'; |
| | removeBtn.addEventListener('click', () => { |
| | container.remove(); |
| | if (typeof feather !== 'undefined') { |
| | feather.replace(); |
| | } |
| | }); |
| | |
| | container.appendChild(img); |
| | container.appendChild(removeBtn); |
| | imagePreview.appendChild(container); |
| | |
| | if (typeof feather !== 'undefined') { |
| | feather.replace(); |
| | } |
| | }; |
| | reader.readAsDataURL(file); |
| | }); |
| | } |
| | |
| | }); |