// Theme toggle functionality document.addEventListener('DOMContentLoaded', () => { const themeToggle = document.getElementById('themeToggle'); const prefersDarkScheme = window.matchMedia('(prefers-color-scheme: dark)'); // Check for saved theme preference or use system preference const currentTheme = localStorage.getItem('theme') || (prefersDarkScheme.matches ? 'dark' : 'light'); // Apply the current theme if (currentTheme === 'dark') { document.documentElement.classList.add('dark'); themeToggle.innerHTML = ' Light Mode'; } else { document.documentElement.classList.remove('dark'); themeToggle.innerHTML = ' Dark Mode'; } // Set up the toggle button themeToggle.addEventListener('click', () => { const isDark = document.documentElement.classList.contains('dark'); if (isDark) { document.documentElement.classList.remove('dark'); localStorage.setItem('theme', 'light'); themeToggle.innerHTML = ' Dark Mode'; } else { document.documentElement.classList.add('dark'); localStorage.setItem('theme', 'dark'); themeToggle.innerHTML = ' Light Mode'; } feather.replace(); }); // Watch for system theme changes prefersDarkScheme.addEventListener('change', e => { if (localStorage.getItem('theme') === null) { if (e.matches) { document.documentElement.classList.add('dark'); } else { document.documentElement.classList.remove('dark'); } } }); // MediaPipe Selfie Segmentation setup let selfieSegmentation; let segmentationActive = false; async function setupSegmentation() { selfieSegmentation = new SelfieSegmentation({ locateFile: (file) => { return `https://cdn.jsdelivr.net/npm/@mediapipe/selfie_segmentation/${file}`; } }); selfieSegmentation.setOptions({ modelSelection: 1, // 0 for general segmentation, 1 for landscape (better for full body) selfieMode: false }); await selfieSegmentation.initialize(); } // Image upload and clothing selection functionality const imageUpload = document.getElementById('imageUpload'); const imagePreview = document.getElementById('imagePreview'); const previewImage = document.getElementById('previewImage'); const toolsPanel = document.getElementById('toolsPanel'); const selectClothesBtn = document.getElementById('selectClothes'); const clearSelectionBtn = document.getElementById('clearSelection'); const downloadSelectionBtn = document.getElementById('downloadSelection'); const selectionCanvas = document.getElementById('selectionCanvas'); const ctx = selectionCanvas.getContext('2d'); let imageLoaded = false; let selectionMode = false; let selectionPoints = []; imageUpload.addEventListener('change', function(e) { const file = e.target.files[0]; if (file) { const reader = new FileReader(); reader.onload = function(event) { previewImage.onload = function() { // Set canvas dimensions to match image selectionCanvas.width = previewImage.width; selectionCanvas.height = previewImage.height; imageLoaded = true; toolsPanel.classList.remove('hidden'); }; previewImage.src = event.target.result; imagePreview.classList.remove('hidden'); selectionPoints = []; ctx.clearRect(0, 0, selectionCanvas.width, selectionCanvas.height); } reader.readAsDataURL(file); } }); // Initialize clothing selection selectClothesBtn.addEventListener('click', async function() { if (!selfieSegmentation) { await setupSegmentation(); } selectionMode = true; segmentationActive = true; selectionPoints = []; ctx.clearRect(0, 0, selectionCanvas.width, selectionCanvas.height); previewImage.style.cursor = 'crosshair'; // Process image with segmentation model if (imageLoaded) { await processSegmentation(); } }); // Clear selection clearSelectionBtn.addEventListener('click', function() { selectionPoints = []; ctx.clearRect(0, 0, selectionCanvas.width, selectionCanvas.height); previewImage.style.cursor = 'default'; selectionMode = false; segmentationActive = false; }); // Download selection downloadSelectionBtn.addEventListener('click', function() { if (selectionPoints.length > 0) { const tempCanvas = document.createElement('canvas'); const tempCtx = tempCanvas.getContext('2d'); tempCanvas.width = previewImage.width; tempCanvas.height = previewImage.height; // Draw the selected area tempCtx.drawImage(previewImage, 0, 0); // Create mask for selection tempCtx.globalCompositeOperation = 'destination-in'; tempCtx.fillStyle = 'black'; tempCtx.beginPath(); tempCtx.moveTo(selectionPoints[0].x, selectionPoints[0].y); for (let i = 1; i < selectionPoints.length; i++) { tempCtx.lineTo(selectionPoints[i].x, selectionPoints[i].y); } tempCtx.closePath(); tempCtx.fill(); // Create download link const link = document.createElement('a'); link.download = 'selected-clothing.png'; link.href = tempCanvas.toDataURL('image/png'); link.click(); } }); // Process image with segmentation model async function processSegmentation() { if (!selfieSegmentation || !imageLoaded) return; try { const result = await selfieSegmentation.send({image: previewImage}); const mask = result.segmentationMask; // Draw the segmentation mask ctx.clearRect(0, 0, selectionCanvas.width, selectionCanvas.height); ctx.drawImage(mask, 0, 0, selectionCanvas.width, selectionCanvas.height); // Apply the mask to highlight clothing ctx.globalCompositeOperation = 'source-in'; ctx.fillStyle = 'rgba(59, 130, 246, 0.5)'; ctx.fillRect(0, 0, selectionCanvas.width, selectionCanvas.height); ctx.globalCompositeOperation = 'source-over'; } catch (error) { console.error('Segmentation error:', error); } } // Handle selection drawing imagePreview.addEventListener('click', function(e) { if (!selectionMode || !imageLoaded) return; const rect = previewImage.getBoundingClientRect(); const x = e.clientX - rect.left; const y = e.clientY - rect.top; selectionPoints.push({x, y}); // Draw selection ctx.clearRect(0, 0, selectionCanvas.width, selectionCanvas.height); ctx.strokeStyle = '#3B82F6'; ctx.lineWidth = 2; ctx.fillStyle = 'rgba(59, 130, 246, 0.2)'; if (selectionPoints.length > 0) { ctx.beginPath(); ctx.moveTo(selectionPoints[0].x, selectionPoints[0].y); for (let i = 1; i < selectionPoints.length; i++) { ctx.lineTo(selectionPoints[i].x, selectionPoints[i].y); } if (selectionPoints.length > 2) { ctx.closePath(); ctx.fill(); } ctx.stroke(); } }); });