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

    Ícone de configuração representando arquivos plist com plistlib no Python
    Bibliotecas e Módulos
    Foto de perfil de Leandro Hirt da Academify

    plistlib no Python: 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
    Mensagem digital representando codificação quoted-printable com quopri no Python
    Bibliotecas e Módulos
    Foto de perfil de Leandro Hirt da Academify

    quopri no Python: quoted-printable

    Aprenda quopri no Python para codificar e decodificar quoted-printable em e-mails, arquivos e integrações MIME com segurança.

    Ler mais

    Tempo de leitura: 7 minutos
    08/08/2026
    Ícone de arquivo digital representando tipos MIME com mimetypes no Python
    Bibliotecas e Módulos
    Foto de perfil de Leandro Hirt da Academify

    mimetypes no Python: tipos MIME

    Aprenda mimetypes no Python para identificar tipos MIME, extensões e encodings com segurança em uploads, downloads e APIs web.

    Ler mais

    Tempo de leitura: 7 minutos
    08/08/2026
    Busca binária e listas ordenadas com bisect no Python
    Bibliotecas e Módulos
    Foto de perfil de Leandro Hirt da Academify

    bisect no Python: buscas em listas ordenadas

    Aprenda bisect no Python para buscar posições, inserir valores e trabalhar com duplicatas e faixas em listas ordenadas.

    Ler mais

    Tempo de leitura: 5 minutos
    08/08/2026
    Código e arquivos empacotados com importlib.resources no Python
    Bibliotecas e Módulos
    Foto de perfil de Leandro Hirt da Academify

    importlib.resources no Python: guia prático

    Aprenda importlib.resources no Python para acessar arquivos empacotados com segurança em pacotes, wheels e aplicações instaladas.

    Ler mais

    Tempo de leitura: 6 minutos
    07/08/2026