about summary refs log tree commit diff stats
path: root/js/lut-cam
diff options
context:
space:
mode:
authorelioat <elioat@tilde.institute>2024-08-14 22:24:17 -0400
committerelioat <elioat@tilde.institute>2024-08-14 22:24:17 -0400
commit91851865712e188650ea11a046c8de2c22674548 (patch)
treeedbc32992d5561a1851848e3fe829125ddf32a1a /js/lut-cam
parent391793456f87ccba1a8e1775e1695ced9594ae33 (diff)
downloadtour-91851865712e188650ea11a046c8de2c22674548.tar.gz
*
Diffstat (limited to 'js/lut-cam')
-rw-r--r--js/lut-cam/index.html74
-rw-r--r--js/lut-cam/lut.js128
2 files changed, 202 insertions, 0 deletions
diff --git a/js/lut-cam/index.html b/js/lut-cam/index.html
new file mode 100644
index 0000000..f31c465
--- /dev/null
+++ b/js/lut-cam/index.html
@@ -0,0 +1,74 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>LUT Cam</title>
+    <style>
+        body, html {
+            margin: 0;
+            padding: 0;
+            width: 100%;
+            height: 100%;
+            display: flex;
+            justify-content: center;
+            align-items: center;
+            background-color: #000;
+        }
+        #canvas {
+            width: 100%;
+            height: 100%;
+            object-fit: cover;
+            display: none;
+        }
+        #controls {
+            position: absolute;
+            bottom: 10px;
+            width: 100%;
+            display: flex;
+            justify-content: center;
+            align-items: center;
+            gap: 10px;
+        }
+        #lut-container {
+            position: absolute;
+            top: 10px;
+            right: 10px;
+        }
+        button, select {
+            padding: 10px;
+            font-size: 18px;
+            cursor: pointer;
+        }
+    </style>
+</head>
+<body>
+
+<canvas id="canvas"></canvas>
+
+<div id="lut-container">
+    <select id="lut-select" disabled>
+        <option value="none">None</option>
+        <option value="lut1">Inverted</option>
+        <option value="lut2">Enhanced</option>
+        <option value="lut3">Subtle Cool Tone</option>
+        <option value="lut4">Subtle Warm Tone</option>
+        <option value="lut5">Subtle Green Tone</option>
+        <option value="lut6">Subtle Yellow Tone</option>
+        <option value="lut7">Desaturated</option>
+        <option value="lut8">Saturated</option>
+        <option value="lut9">Warm Tint</option>
+        <option value="lut10">Cool Tint</option>
+        <option value="lut11">Greyscale</option>
+        <option value="lut12">Sepia</option>
+    </select>
+</div>
+
+<div id="controls">
+    <button id="toggle-camera">Turn Camera On</button>
+    <button id="capture" disabled>Capture Frame</button>
+</div>
+
+<script src="lut.js"></script>
+</body>
+</html>
diff --git a/js/lut-cam/lut.js b/js/lut-cam/lut.js
new file mode 100644
index 0000000..6466f32
--- /dev/null
+++ b/js/lut-cam/lut.js
@@ -0,0 +1,128 @@
+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], // Inverted Colors
+    'lut2': (r, g, b) => [r * 1.2, g * 0.8, b * 1.5], // Enhanced Colors
+    'lut3': (r, g, b) => [r * 0.9, g * 0.9, b * 1.1], // Subtle Cool Tone
+    'lut4': (r, g, b) => [r * 1.1, g * 0.9, b * 0.9], // Subtle Warm Tone
+    'lut5': (r, g, b) => [r * 0.9, g * 1.1, b * 0.9], // Subtle Green Tone
+    'lut6': (r, g, b) => [r * 1.1, g * 1.1, b * 0.9], // Subtle Yellow Tone
+    'lut7': (r, g, b) => [r * 0.9, g * 0.9, b * 0.9], // Desaturated
+    'lut8': (r, g, b) => [r * 1.1, g * 1.1, b * 1.1], // Saturated
+    'lut9': (r, g, b) => [r * 0.9, g * 1.1, b * 1.1], // Warm Tint
+    'lut10': (r, g, b) => [r * 1.1, g * 0.9, b * 0.9], // Cool Tint
+    'lut11': (r, g, b) => { const avg = (r + g + b) / 3; return [avg, avg, avg]; }, // Greyscale
+    'lut12': (r, g, b) => { const avg = (r + g + b) / 3; return [avg * 1.1, avg * 0.9, avg * 0.9]; } // Sepia
+};
+
+let currentLUT = 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;
+
+            // Display the video feed on the canvas
+            video.addEventListener('play', function() {
+                function step() {
+                    if (!cameraOn) return; // Don't show the video feed if there isn't a video feed to show
+                    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';
+        lutSelect.disabled = true;
+        captureButton.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();
+});