about summary refs log blame commit diff stats
path: root/js/lut-cam/lut.js
blob: ff2bb416edc1e6e5474f97b66a2465b21618ac88 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16















                                                                    












                                                                                                      



                      


                                                            








                                                                                            










                                                                                     
 













                                                                               

                                                       
                                          















                                                           
                                                         

                                      

                                     



                      
 


























































                                                                                             










                                                                                                  
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const video = document.createElement('video');
const toggleCameraButton = document.getElementById('toggle-camera');
const lutSelect = document.getElementById('lut-select');
const captureButton = document.getElementById('capture');

let cameraOn = false;
let stream = null;

// Set the canvas dimensions to match the window size
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

const LUTs = {
    'none': null,
    'lut1': (r, g, b) => [255 - r, 255 - g, 255 - b],
    'lut2': (r, g, b) => [r * 1.2, g * 0.8, b * 1.5],
    'lut3': (r, g, b) => [r * 0.9, g * 0.9, b * 1.1], 
    'lut4': (r, g, b) => [r * 1.1, g * 0.9, b * 0.9],
    'lut5': (r, g, b) => [r * 0.9, g * 1.1, b * 0.9],
    'lut6': (r, g, b) => [r * 1.1, g * 1.1, b * 0.9], 
    'lut7': (r, g, b) => [r * 0.9, g * 0.9, b * 0.9],
    'lut8': (r, g, b) => [r * 1.1, g * 1.1, b * 1.1],
    'lut9': (r, g, b) => [r * 0.9, g * 1.1, b * 1.1],
    'lut10': (r, g, b) => [r * 1.1, g * 0.9, b * 0.9],
    'lut11': (r, g, b) => { const avg = (r + g + b) / 3; return [avg, avg, avg]; },
    'lut12': (r, g, b) => { const avg = (r + g + b) / 3; return [avg * 1.1, avg * 0.9, avg * 0.9]; }, 
    'lut13': (r, g, b) => [r * 1.5, g * 1.5, b * 1.5]
};

let currentLUT = null;

const focusSlider = document.getElementById('focus-slider');
let track = null;

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
            lutSelect.disabled = false;
            captureButton.disabled = false;
            captureButton.active = true;
            focusSlider.disabled = false;

            track = stream.getVideoTracks()[0];
            const settings = track.getSettings();

            // So, I don't seem to have a device where this is supported
            // Check if focus control is supported with this browser and device combo
            if ('focusDistance' in settings) {
                // If it is available, enable the slider for focus control
                focusSlider.style.display = 'block';

                // Set initial focus value, and a fallback
                focusSlider.value = settings.focusDistance || focusSlider.min;

                focusSlider.addEventListener('input', () => {
                    track.applyConstraints({
                        advanced: [{ focusDistance: focusSlider.value }]
                    });
                });
            } else {
                console.warn('Focus control is not supported on this device.');
                focusSlider.style.display = 'none';
            }

            // Draw the video feed to the canvas
            video.addEventListener('play', function() {
                function step() {
                    if (!cameraOn) return;
                    drawVideoProportional();
                    applyLUT();
                    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
        lutSelect.disabled = true;
        captureButton.disabled = true;
        captureButton.active = false;
        focusSlider.disabled = true;
        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;

    ctx.clearRect(0, 0, canvas.width, canvas.height); // Clear the canvas
    ctx.drawImage(video, offsetX, offsetY, drawWidth, drawHeight); // Draw the video normally
}

function applyLUT() {
    if (!currentLUT) return;

    const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
    const data = imageData.data;

    for (let i = 0; i < data.length; i += 4) {
        const [r, g, b] = currentLUT(data[i], data[i + 1], data[i + 2]);
        data[i] = r;
        data[i + 1] = g;
        data[i + 2] = b;
    }

    ctx.putImageData(imageData, 0, 0);
}

toggleCameraButton.addEventListener('click', () => {
    cameraOn = !cameraOn;
    if (cameraOn) {
        startCamera();
        toggleCameraButton.textContent = 'Turn Camera Off';
    } else {
        stopCamera();
        toggleCameraButton.textContent = 'Turn Camera On';
    }
});

lutSelect.addEventListener('change', () => {
    const selectedLUT = lutSelect.value;
    currentLUT = LUTs[selectedLUT];
});

captureButton.addEventListener('click', () => {
    const link = document.createElement('a');
    link.download = 'captured-image.png';
    link.href = canvas.toDataURL('image/png');
    link.click();
});

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);
        });
    });
}