Skip to content

Instantly share code, notes, and snippets.

@guiseek
Created May 12, 2023 05:57
Show Gist options
  • Save guiseek/570fc5ca90a217bb307b3af100efc992 to your computer and use it in GitHub Desktop.
Save guiseek/570fc5ca90a217bb307b3af100efc992 to your computer and use it in GitHub Desktop.
import './style.scss'
const video = document.querySelector('video') as HTMLVideoElement;
const canvas = document.querySelector('canvas') as HTMLCanvasElement;
const ctx = canvas.getContext('2d', { willReadFrequently: true })!;
// Configuração da tela de fundo
const BACKGROUND_COLOR = [6, 6, 6]; // fundo verde
const TOLERANCE = 80; // tolerância de cor
const OPACITY = 0.7; // opacidade do sujeito
const MAX_ITERATIONS = 1000000; // número máximo de iterações para preencher o fundo
const PIXEL_STACK_LIMIT = 100000; // limite de pilha de pixel para preencher o fundo
// Iniciar a reprodução do vídeo
video.onplay = () => {
canvas.width = video.videoWidth
canvas.height = video.videoHeight
}
// video.play();
// Desenhar a imagem na tela a cada quadro
function drawFrame() {
// desenhar o quadro atual do vídeo no canvas
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
// obter os pixels da imagem
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
const pixels = imageData.data;
// percorrer os pixels da imagem
const stack = [[0, 0]]; // pilha de pixel para preencher o fundo
const visited = new Set(); // pixels já visitados
while (stack.length > 0) {
// obter o próximo pixel da pilha
const [x, y] = stack.pop() ?? [];
const index = (y * canvas.width + x) * 4;
// verificar se o pixel já foi visitado
if (visited.has(index)) {
continue;
}
visited.add(index);
// verificar se o pixel está próximo o suficiente da cor de fundo
const distance = Math.sqrt(
Math.pow(pixels[index] - BACKGROUND_COLOR[0], 2) +
Math.pow(pixels[index + 1] - BACKGROUND_COLOR[1], 2) +
Math.pow(pixels[index + 2] - BACKGROUND_COLOR[2], 2)
);
if (distance <= TOLERANCE) {
// preencher o pixel com a cor de fundo
pixels[index + 3] = OPACITY * 255;
// empilhar pixels vizinhos
if (stack.length < PIXEL_STACK_LIMIT) {
if (x > 0) {
stack.push([x - 1, y]);
}
if (x < canvas.width - 1) {
stack.push([x + 1, y]);
}
if (y > 0) {
stack.push([x, y - 1]);
}
if (y < canvas.height - 1) {
stack.push([x, y + 1]);
}
}
// verificar se atingimos o número máximo de iterações
if (visited.size >= MAX_ITERATIONS) {
break;
}
}
}
// desenhar a imagem atualizada no canvas
ctx.putImageData(imageData, 0, 0);
// chamar esta função novamente na próxima animação de quadro
// requestAnimationFrame(drawFrame);
video.requestVideoFrameCallback(drawFrame)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment