colorsys no Python: RGB, HSV e HLS

Publicado em: 09/08/2026
Tempo de leitura: 6 minutos
Círculo cromático representando conversões RGB, HSV e HLS com colorsys no Python

Interfaces, gráficos, ferramentas de imagem e sistemas de design frequentemente precisam transformar uma cor entre representações diferentes. O módulo colorsys no Python fornece conversões bidirecionais entre RGB e os modelos HSV, HLS e YIQ usando apenas a biblioteca padrão.

O módulo é pequeno, mas exige atenção à escala: quase todos os componentes são floats entre 0 e 1. Ele também não gerencia perfis ICC, gama, espaços como Lab ou diferenças perceptuais. Neste guia você aprenderá a normalizar valores, criar paletas, ajustar brilho e saturação, testar conversões e entender os limites matemáticos.

O conteúdo complementa nossos artigos sobre Decimal, fractions, statistics, filecmp e mimetypes.

Modelos de cor disponíveis

O módulo converte RGB para três sistemas:

  • HSV: hue, saturation e value;
  • HLS: hue, lightness e saturation;
  • YIQ: luminância e dois componentes de crominância.

As funções inversas transformam cada modelo novamente em RGB.

Escala normalizada

Em RGB, HSV e HLS, os componentes ficam normalmente entre 0 e 1. Isso difere do formato comum de 8 bits, que usa 0 a 255.

def rgb_255_para_unitario(r, g, b):
    return r / 255, g / 255, b / 255


def rgb_unitario_para_255(r, g, b):
    return tuple(round(c * 255) for c in (r, g, b))

Normalize antes da conversão e volte para inteiros apenas no limite da aplicação.

RGB para HSV

import colorsys

rgb = rgb_255_para_unitario(51, 102, 102)
h, s, v = colorsys.rgb_to_hsv(*rgb)
print(h, s, v)

Hue representa a posição no círculo de cores, saturation representa a intensidade cromática e value representa o maior componente RGB.

HSV para RGB

r, g, b = colorsys.hsv_to_rgb(h, s, v)
print(rgb_unitario_para_255(r, g, b))

Conversões de ida e volta podem produzir pequenas diferenças devido a ponto flutuante e arredondamento para 8 bits.

Hue como círculo

Hue é cíclico: zero e um representam a mesma direção. Para girar a cor, use módulo.

novo_h = (h + 30 / 360) % 1.0

Somar 30 graus equivale a adicionar 30/360 na escala normalizada.

Gerar uma paleta por matiz

def paleta(h_inicial, quantidade):
    cores = []
    for indice in range(quantidade):
        h = (h_inicial + indice / quantidade) % 1.0
        cores.append(colorsys.hsv_to_rgb(h, 0.7, 0.9))
    return cores

Esse exemplo distribui matizes igualmente, mas igualdade angular não garante contraste perceptual nem acessibilidade.

Ajustar saturação

def alterar_saturacao(rgb, fator):
    h, s, v = colorsys.rgb_to_hsv(*rgb)
    s = min(1.0, max(0.0, s * fator))
    return colorsys.hsv_to_rgb(h, s, v)

Limite o resultado para evitar valores fora da faixa. Fator zero produz cinza; valores maiores intensificam a cor até o limite.

Ajustar brilho com HSV

def alterar_valor(rgb, delta):
    h, s, v = colorsys.rgb_to_hsv(*rgb)
    v = min(1.0, max(0.0, v + delta))
    return colorsys.hsv_to_rgb(h, s, v)

O componente value não é luminância perceptual. Aumentá-lo pode não produzir a mesma sensação de brilho em todas as cores.

RGB para HLS

h, l, s = colorsys.rgb_to_hls(*rgb)

Observe a ordem: a função usa H, L, S. Muitos sistemas web usam a sigla HSL e exibem hue, saturation, lightness. Confundir a ordem gera resultados errados.

Ajustar lightness

def clarear_hls(rgb, quantidade):
    h, l, s = colorsys.rgb_to_hls(*rgb)
    l = min(1.0, l + quantidade)
    return colorsys.hls_to_rgb(h, l, s)

HLS pode ser intuitivo para criar variantes claras e escuras, mas também não é uniforme do ponto de vista perceptual.

HSV versus HLS

HSV usa value e HLS usa lightness. Os dois modelos organizam RGB de maneiras diferentes. Uma saturação de 100% em HLS não possui exatamente o mesmo significado visual que 100% em HSV.

Escolha o modelo conforme a operação. HSV é comum para seletores e intensidade; HLS pode ser mais intuitivo para variantes claras e escuras.

Modelo YIQ

YIQ foi usado no sistema de televisão NTSC. O componente Y representa luminância aproximada, enquanto I e Q carregam crominância.

y, i, q = colorsys.rgb_to_yiq(*rgb)
r, g, b = colorsys.yiq_to_rgb(y, i, q)

Y fica entre 0 e 1, mas I e Q podem ser positivos ou negativos. Não aplique o mesmo clamp de 0 a 1 a esses componentes.

Escala hexadecimal

def hex_para_rgb(cor):
    valor = cor.lstrip("#")
    if len(valor) != 6:
        raise ValueError("use #RRGGBB")
    return tuple(int(valor[i:i+2], 16) / 255 for i in (0, 2, 4))


def rgb_para_hex(rgb):
    r, g, b = rgb_unitario_para_255(*rgb)
    return f"#{r:02X}{g:02X}{b:02X}"

Valide o formato antes de converter e defina se versões abreviadas ou alpha são permitidas.

Clamping seguro

def clamp(valor, minimo=0.0, maximo=1.0):
    return min(maximo, max(minimo, valor))

Use clamp depois de operações aritméticas, não para esconder entrada inválida. Em APIs, valores fora da faixa podem indicar um erro que merece exceção.

Ponto flutuante

Resultados como 0.30000000000000004 são normais em binário. Compare com tolerância.

import math

assert math.isclose(restaurado, original, abs_tol=1e-9)

Ao converter para 8 bits, arredonde uma vez no final.

Cores acromáticas

Quando saturação é zero, hue não tem significado visual. O módulo ainda devolve um valor numérico, normalmente zero.

Aplicações que armazenam a intenção do usuário podem precisar manter o hue anterior separadamente para que ele reapareça ao aumentar a saturação.

Alpha não é suportado

colorsys trabalha com três componentes. Preserve o canal alpha fora da conversão.

r, g, b, a = cor_rgba
h, s, v = colorsys.rgb_to_hsv(r, g, b)
# a permanece separado

Gama e espaço RGB

Os valores RGB comuns de telas geralmente estão codificados em sRGB com curva de transferência. As fórmulas de colorsys operam diretamente sobre os números fornecidos. Elas não linearizam sRGB nem convertem perfis.

Para composição física, iluminação, impressão e processamento científico, use bibliotecas que tratem gama e gerenciamento de cores.

Contraste e acessibilidade

Gerar cores diferentes em HSV não garante contraste de texto suficiente. Calcule contraste segundo as regras de acessibilidade e teste daltonismo e temas claros e escuros.

Não use apenas matiz para transmitir estado; combine texto, ícones ou padrões.

Paleta complementar

def complementar(rgb):
    h, s, v = colorsys.rgb_to_hsv(*rgb)
    return colorsys.hsv_to_rgb((h + 0.5) % 1.0, s, v)

A cor matematicamente oposta pode não ser a melhor escolha visual. Trate o resultado como ponto de partida.

Paleta análoga

def analogas(rgb, graus=30):
    h, s, v = colorsys.rgb_to_hsv(*rgb)
    deslocamento = graus / 360
    return [
        colorsys.hsv_to_rgb((h - deslocamento) % 1, s, v),
        rgb,
        colorsys.hsv_to_rgb((h + deslocamento) % 1, s, v),
    ]

Processar muitas cores

O módulo é escrito para conversões escalares. Em milhões de pixels, loops Python podem ser lentos. Bibliotecas vetorizadas de imagem ou arrays são mais adequadas.

Para pequenas paletas, temas e configurações, a simplicidade da biblioteca padrão é excelente.

Testes de ida e volta

def test_hsv_round_trip():
    original = (0.2, 0.4, 0.7)
    hsv = colorsys.rgb_to_hsv(*original)
    restaurado = colorsys.hsv_to_rgb(*hsv)
    for a, b in zip(original, restaurado):
        assert math.isclose(a, b, abs_tol=1e-9)

Teste preto, branco, tons de cinza, cores primárias, limites e valores próximos de zero e um.

Validar entrada

def validar_rgb(rgb):
    if len(rgb) != 3:
        raise ValueError("RGB precisa de três componentes")
    if not all(0.0 <= c <= 1.0 for c in rgb):
        raise ValueError("componentes fora da faixa")

Não deixe NaN ou infinito entrar em pipelines de cor. Use math.isfinite().

Erros frequentes

  • Passar valores de 0 a 255 sem normalizar.
  • Confundir a ordem HLS com HSL de outra API.
  • Aplicar clamp de 0 a 1 em I e Q.
  • Arredondar em cada etapa.
  • Descartar alpha sem perceber.
  • Usar HSV como medida perceptual.
  • Ignorar perfis e gama em processamento profissional.
  • Confiar apenas em matiz para acessibilidade.

Boas práticas

  • Normalize componentes na borda da aplicação.
  • Mantenha floats durante os cálculos.
  • Use módulo para hue.
  • Valide finitude e faixa.
  • Preserve alpha separadamente.
  • Teste contraste de forma independente.
  • Use bibliotecas vetorizadas para imagens grandes.
  • Documente o modelo e a escala de cada função.

Conclusão

O módulo colorsys no Python fornece conversões simples e confiáveis entre RGB, HSV, HLS e YIQ. Ele é ideal para paletas, temas, pequenas ferramentas gráficas e transformações de configuração.

Use-o entendendo seus limites: os valores são normalizados, os modelos não são perceptualmente uniformes e não existe gerenciamento de perfis, gama ou alpha. Consulte a documentação oficial de colorsys e as orientações de contraste da W3C para produzir interfaces mais robustas.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Conteúdo do artigo

    Artigos relacionados

    Documento e caixa de entrada representando caixas de e-mail com mailbox no Python
    Bibliotecas e Módulos
    Foto de perfil de Leandro Hirt da Academify

    mailbox no Python: caixas de e-mail

    Aprenda mailbox no Python para ler, criar e migrar caixas Maildir, mbox e MH com locking, mensagens, flags e tratamento

    Ler mais

    Tempo de leitura: 6 minutos
    12/08/2026
    Editor de texto representando formatação com textwrap no Python
    Bibliotecas e Módulos
    Foto de perfil de Leandro Hirt da Academify

    textwrap no Python: formate textos

    Aprenda textwrap no Python para quebrar, preencher, encurtar, indentar e remover recuos de textos com controle de largura e espaços.

    Ler mais

    Tempo de leitura: 5 minutos
    10/08/2026
    Pasta e lupa representando filtros de nomes com fnmatch no Python
    Bibliotecas e Módulos
    Foto de perfil de Leandro Hirt da Academify

    fnmatch no Python: filtre nomes de arquivos

    Aprenda fnmatch no Python para filtrar nomes de arquivos com curingas, controlar maiúsculas, excluir padrões e evitar confundir glob com

    Ler mais

    Tempo de leitura: 5 minutos
    10/08/2026
    Monitor com dados binários representando arrays numéricos compactos no Python
    Bibliotecas e Módulos
    Foto de perfil de Leandro Hirt da Academify

    array no Python: números compactos

    Aprenda array no Python para armazenar números compactos, manipular bytes, arquivos binários e buffers com segurança.

    Ler mais

    Tempo de leitura: 6 minutos
    10/08/2026
    Ícone de configuração representando arquivos plist com plistlib no Python
    Bibliotecas e Módulos
    Foto de perfil de Leandro Hirt da Academify

    plistlib: leia e grave arquivos plist

    Aprenda plistlib no Python para ler e gravar arquivos plist XML e binários, validar dados e integrar configurações Apple com

    Ler mais

    Tempo de leitura: 7 minutos
    08/08/2026
    Cadeado digital representando credenciais por host com netrc no Python
    Bibliotecas e Módulos
    Foto de perfil de Leandro Hirt da Academify

    netrc no Python: credenciais por host

    Aprenda netrc no Python para ler credenciais por host, validar permissões, tratar erros e integrar clientes de rede com segurança.

    Ler mais

    Tempo de leitura: 7 minutos
    08/08/2026