Val Town is a social website to write and deploy JavaScript.
Build APIs and schedule functions from your browser.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
/**
* This app will create a webcam-based image processing application.
* It will request webcam permissions, display the video feed, and prepare for applying effects.
* We'll use React for the UI, the browser's MediaDevices API for webcam access,
* and later we'll incorporate P5.js for image processing.
*/
/** @jsxImportSource https://esm.sh/react */
import React, { useEffect, useRef, useState } from "https://esm.sh/react";
import { createRoot } from "https://esm.sh/react-dom/client";
function App() {
const videoRef = useRef<HTMLVideoElement>(null);
const canvasRef = useRef<HTMLCanvasElement>(null);
const displayCanvasRef = useRef<HTMLCanvasElement>(null);
const [error, setError] = useState<string | null>(null);
const [effect, setEffect] = useState<string>("pink_zone");
const effectRef = useRef(effect);
useEffect(() => {
effectRef.current = effect;
}, [effect]);
useEffect(() => {
async function setupWebcam() {
try {
const stream = await navigator.mediaDevices.getUserMedia({ video: true });
if (videoRef.current) {
videoRef.current.srcObject = stream;
}
} catch (err) {
setError("Failed to access webcam. Please ensure you've granted permission.");
console.error("Error accessing webcam:", err);
}
}
setupWebcam();
return () => {
if (videoRef.current && videoRef.current.srcObject) {
const stream = videoRef.current.srcObject as MediaStream;
stream.getTracks().forEach(track => track.stop());
}
};
}, []);
useEffect(() => {
const video = videoRef.current;
const canvas = canvasRef.current;
const displayCanvas = displayCanvasRef.current;
if (!video || !canvas || !displayCanvas) return;
const ctx = canvas.getContext("2d");
const displayCtx = displayCanvas.getContext("2d");
if (!ctx || !displayCtx) return;
let animationFrameId: number;
const drawToCanvas = () => {
canvas.width = 64;
canvas.height = 64;
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
const data = imageData.data;
// Apply selected effect
switch (effectRef.current) {
case "pink_zone":
for (let i = 0; i < data.length; i += 4) {
data[i] = data[i] * 2 % 255; // Red
data[i + 1] = data[i + 1] / 2; // Green
data[i + 2] = (data[i + 2] + 100) % 255; // Blue
}
break;
case "storm":
const lightningStrength = Math.random() < 0.05 ? Math.random() * 200 + 55 : 0;
for (let i = 0; i < data.length; i += 4) {
data[i] = Math.min(data[i] / 4, 255); // Reduced Red
data[i + 1] = Math.min(data[i + 1] / 3, 255); // Reduced Green
data[i + 2] = Math.min((data[i + 2] + 50) % 255 + lightningStrength, 255); // Enhanced Blue with lightning
}
break;
case "goth_girl":
for (let i = 0; i < data.length; i += 4) {
const avg = (data[i] + data[i + 1] + data[i + 2]) / 3;
if (avg < 128) {
data[i] = data[i + 1] = data[i + 2] = 0; // Black
} else if (avg < 192) {
data[i] = 102; // Deep purple
data[i + 1] = 0;
data[i + 2] = 153;
} else {
data[i] = data[i + 1] = data[i + 2] = 255; // White
}
}
break;
case "weed_mode":
for (let i = 0; i < data.length; i += 4) {
const avg = (data[i] + data[i + 1] + data[i + 2]) / 3;
kian-webcameffects.web.val.run
August 25, 2024