const canvas = document.getElementById('canvas'); const ctx = canvas.getContext('2d'); const video = document.createElement('video'); const toggleCameraButton = document.getElementById('toggle-camera'); const captureButton = document.getElementById('capture'); const focusControl = document.getElementById('focus-control'); const focusSlider = document.getElementById('focus-slider'); const focusValue = document.getElementById('focus-value'); let cameraOn = false; let stream = null; let track = null; // Initialize managers ColorManager.init(); DitherManager.init(); ContrastManager.init(); BlurManager.init(); BalanceManager.init(); // Set the canvas dimensions to match the window size function updateCanvasSize() { // Get the container dimensions const container = document.querySelector('.preview-container'); const containerWidth = container.clientWidth; const containerHeight = container.clientHeight; // If video is playing, use its aspect ratio if (video.videoWidth && video.videoHeight) { const videoAspect = video.videoWidth / video.videoHeight; const containerAspect = containerWidth / containerHeight; // Determine dimensions that maintain aspect ratio while fitting in container if (containerAspect > videoAspect) { // Container is wider than video canvas.height = containerHeight; canvas.width = containerHeight * videoAspect; } else { // Container is taller than video canvas.width = containerWidth; canvas.height = containerWidth / videoAspect; } } else { // Default to container dimensions until video starts canvas.width = containerWidth; canvas.height = containerHeight; } } // Update canvas size when window is resized window.addEventListener('resize', updateCanvasSize); // Initialize canvas size updateCanvasSize(); function startCamera() { navigator.mediaDevices.getUserMedia({ video: { facingMode: { ideal: 'environment' } } }) .then(s => { stream = s; video.srcObject = stream; video.play(); canvas.style.display = 'block'; // Show the canvas captureButton.disabled = false; captureButton.active = true; track = stream.getVideoTracks()[0]; const settings = track.getSettings(); // Check if focus control is supported with this browser and device combo if ('focusDistance' in settings) { focusControl.style.display = 'flex'; focusSlider.disabled = false; focusSlider.value = settings.focusDistance || focusSlider.min; focusValue.textContent = `${focusSlider.value}%`; focusSlider.addEventListener('input', () => { const value = focusSlider.value; focusValue.textContent = `${value}%`; track.applyConstraints({ advanced: [{ focusDistance: value }] }); }); } else { console.warn('Focus control is not supported on this device.'); focusControl.style.display = 'none'; } // Draw the video feed to the canvas video.addEventListener('play', function() { function step() { if (!cameraOn) return; drawVideoProportional(); applyContrast(); applyColorTint(); applyBlur(); applyBalance(); applyDither(); requestAnimationFrame(step); } requestAnimationFrame(step); }); }) .catch(err => { console.error('Error accessing camera: ', err); }); } function stopCamera() { if (stream) { stream.getTracks().forEach(track => track.stop()); video.pause(); canvas.style.display = 'none'; // hide the canvas captureButton.disabled = true; captureButton.active = false; focusSlider.disabled = true; focusControl.style.display = 'none'; stream = null; } } function drawVideoProportional() { const videoAspectRatio = video.videoWidth / video.videoHeight; const canvasAspectRatio = canvas.width / canvas.height; let drawWidth, drawHeight; if (canvasAspectRatio > videoAspectRatio) { drawHeight = canvas.height; drawWidth = videoAspectRatio * drawHeight; } else { drawWidth = canvas.width; drawHeight = drawWidth / videoAspectRatio; } const offsetX = (canvas.width - drawWidth) / 2; const offsetY = (canvas.height - drawHeight) / 2; // Draw the video content centered ctx.drawImage(video, offsetX, offsetY, drawWidth, drawHeight); } function applyColorTint() { const currentColor = ColorManager.getCurrentColor(); if (!currentColor) return; const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); const tintedImageData = ColorManager.applyTint(imageData, currentColor); ctx.putImageData(tintedImageData, 0, 0); } function applyBalance() { const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); const balancedImageData = BalanceManager.applyBalance(imageData); ctx.putImageData(balancedImageData, 0, 0); } function applyContrast() { const currentContrast = ContrastManager.getCurrentContrast(); if (!currentContrast || currentContrast === 1.0) return; const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); const contrastedImageData = ContrastManager.applyContrast(imageData, currentContrast); ctx.putImageData(contrastedImageData, 0, 0); } function applyDither() { const currentMode = DitherManager.getCurrentMode(); if (!currentMode || currentMode === 'none') return; const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); const ditheredImageData = DitherManager.applyDither(imageData, currentMode); ctx.putImageData(ditheredImageData, 0, 0); } function applyBlur() { const currentBlur = BlurManager.getCurrentBlur(); if (!currentBlur) return; const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); const blurredImageData = BlurManager.applyBlur(imageData, currentBlur); ctx.putImageData(blurredImageData, 0, 0); } captureButton.addEventListener('click', () => { const currentColor = ColorManager.getCurrentColor(); const borderWidth = 4; // Create a canvas with extra space for the border const captureCanvas = document.createElement('canvas'); const captureCtx = captureCanvas.getContext('2d'); // Set dimensions including border captureCanvas.width = canvas.width + (borderWidth * 2); captureCanvas.height = canvas.height + (borderWidth * 2); // Fill with border color if a tint is selected if (currentColor) { captureCtx.fillStyle = currentColor; captureCtx.fillRect(0, 0, captureCanvas.width, captureCanvas.height); } // Draw the main canvas content captureCtx.drawImage(canvas, borderWidth, borderWidth); const link = document.createElement('a'); link.download = 'captured-image.png'; link.href = captureCanvas.toDataURL('image/png'); link.click(); }); toggleCameraButton.addEventListener('click', () => { cameraOn = !cameraOn; if (cameraOn) { startCamera(); toggleCameraButton.textContent = 'Camera Off'; } else { stopCamera(); toggleCameraButton.textContent = 'Camera On'; } }); if ('serviceWorker' in navigator) { window.addEventListener('load', () => { navigator.serviceWorker.register('/service-worker.js') .then(registration => { console.log('ServiceWorker registration successful with scope: ', registration.scope); }, err => { console.log('ServiceWorker registration failed: ', err); }); }); } ColorManager._setupEventListeners();