Pixels, cores e representação
Como monitores representam cor com três números, o que significam RGB e HSL, e por que uma imagem Full HD ocupa 8 MB por frame.
Tudo é um grid de números
Um monitor nada mais é que uma grade de pequenos pontos de luz — os pixels (picture elements). Cada pixel emite três cores primárias de luz: vermelho (R), verde (G) e azul (B). Controlando a intensidade de cada uma (0 a 255), o olho humano percebe praticamente qualquer cor.
Um pixel é armazenado na memória como 4 bytes contíguos: R, G, B e A (transparência). Uma tela Full HD (1920×1080) tem 2.073.600 pixels — cerca de 8 MB de dados por frame. A 60 fps, isso é quase 480 MB/s de dados sendo escritos na memória de vídeo.
Misturador de cores
Ajuste os sliders R/G/B das duas cores e veja a mistura linear. Observe os valores em hex, RGB e HSL.
Pixels em memória e modelos de cor
// Representação de pixels em memória // Imagem RGBA: 4 bytes por pixel const largura = 1920, altura = 1080; const bytesTotal = largura * altura * 4; // 8.294.400 bytes ≈ 8 MB por frame // Acessar o pixel (x=100, y=50): const offset = (y * largura + x) * 4; const r = imageData[offset]; // Red 0-255 const g = imageData[offset + 1]; // Green 0-255 const b = imageData[offset + 2]; // Blue 0-255 const a = imageData[offset + 3]; // Alpha 0-255 // CSS no fundo usa a mesma representação: // #ff6b6b = r:255, g:107, b:107 // rgb(255, 107, 107) = mesma coisa, mais legível // hsl(0°, 100%, 71%) = mesma cor, modelo diferente
Por que HSL existe?
RGB é ótimo para hardware, mas terrível para humanos. Para "escurecer" um vermelho em RGB você teria que reduzir R=255 para R=128 — não intuitivo. Em HSL você só mexe no Lightness (L). O H (Hue/matiz) é o ângulo na roda de cores (0°=vermelho, 120°=verde, 240°=azul), S (Saturation) controla a vivacidade e L (Lightness) a luminosidade.
// Conversão RGB → HSL function rgbToHsl(r, g, b) { r /= 255; g /= 255; b /= 255; const max = Math.max(r, g, b); const min = Math.min(r, g, b); const l = (max + min) / 2; // Luminosidade if (max === min) return [0, 0, l]; // Cinza const d = max - min; const s = l > 0.5 ? d / (2 - max - min) : d / (max + min); // Saturação // Hue: qual canal domina? let h; if (max === r) h = (g - b) / d + (g < b ? 6 : 0); else if (max === g) h = (b - r) / d + 2; else h = (r - g) / d + 4; return [h / 6 * 360, s * 100, l * 100]; // Hue°, Sat%, Light% }
Manipulação de pixels com Canvas
Mini projeto: use ctx.getImageData() do Canvas para inverter as cores de uma imagem: para cada pixel, faça R = 255 - R, G = 255 - G, B = 255 - B. Use ctx.putImageData() para atualizar.
Projeto principal: implemente um filtro "sepiatone" (tons sépia): para cada pixel, calcule newR = 0.393R + 0.769G + 0.189B, newG = 0.349R + 0.686G + 0.168B, newB = 0.272R + 0.534G + 0.131B. Clamp em 255. Aplique em tempo real em um stream de câmera (getUserMedia).
Desafio extra: implemente um seletor de cores no estilo "Color Picker" que converte em tempo real entre RGB, HSL e CMYK — tudo sem usar bibliotecas, só as fórmulas matemáticas de conversão.
Teste sua intuição
Onde você encontra isso
Filtros de foto/vídeo
Instagram, Photoshop e DaVinci Resolve manipulam pixels com matrizes de cor (color grading). Um "filtro de filme" é literalmente uma transformação matemática aplicada a cada pixel — às vezes com uma lookup table (LUT) de 33³ entradas.
HDR em jogos
Jogos modernos renderizam internamente em espaço de cor linear com 16 bits float por canal (HDR), depois aplicam tone mapping para converter para o display de 8 bits. Sem isso, áreas muito brilhantes ficam "queimadas" — sem detalhe.
CSS Color Level 5
CSS moderno suporta oklch(), lab() e display-p3 — espaços de cor perceptualmente uniformes que cobrem 25% mais cores que sRGB. Monitores Apple (P3) e OLED modernos exibem essas cores extras.