Skip to content
ClickHouse Docs
ClickHouse DocsClickHouse Docs

PNG

Entrada Saída Alias

Descrição

Renderiza o resultado de uma consulta como uma imagem PNG. Isso é útil como uma ferramenta de visualização integrada.

O tamanho da imagem de saída é definido pelas configurações output_format_image_width e output_format_image_height (ambas com valor padrão de 1024). Os pixels não cobertos pelo resultado são preenchidos com preto (nos modos RGB e em escala de cinza) ou com preto transparente (no modo RGBA).

O modo de cor é determinado automaticamente com base nos nomes e tipos das colunas do resultado:

Colunas Modo
r, g, b RGB de 8 bits
r, g, b, a RGBA de 8 bits
v do tipo inteiro escala de cinza de 8 bits
v do tipo Float* escala de cinza de 8 bits (valores em [0, 1][0, 255])
v do tipo Bool Binário (renderizado como escala de cinza de 8 bits: 0 ou 255)

Os nomes das colunas são comparados sem diferenciar maiúsculas de minúsculas. Se o modo de cor não puder ser determinado de forma inequívoca (por exemplo, nomes de colunas desconhecidos, v misturado com r/g/b/a ou ausência de um de r/g/b), a consulta lança uma exceção.

Para os canais de pixel, os valores inteiros são limitados ao intervalo [0, 255], e os valores de ponto flutuante são limitados ao intervalo [0, 1] e depois escalados para [0, 255].

A posição de cada registro na imagem é determinada por um de dois modos:

  • Implícito (o padrão — quando nem x nem y está presente). Cada registro corresponde a um único pixel; os pixels são preenchidos em ordem de varredura: da esquerda para a direita, de cima para baixo.
  • Explícito (quando as colunas x e y estão presentes, ambas de tipos inteiros). As colunas x e y fornecem as coordenadas do pixel. Registros com coordenadas fora da imagem são ignorados sem aviso. No caso de vários registros com as mesmas coordenadas, o último prevalece (algoritmo do pintor).

Exemplo de uso

Coordenadas implícitas (linha por pixel), RGB

SELECT
    toUInt8(x * 25) AS r,
    toUInt8(y * 25) AS g,
    toUInt8((x + y) * 12) AS b
FROM
(
    SELECT number % 10 AS x, intDiv(number, 10) AS y FROM numbers(100)
)
INTO OUTFILE 'gradient.png'
FORMAT PNG
SETTINGS output_format_image_width = 10, output_format_image_height = 10;

Coordenadas explícitas, escala de cinza

SELECT
    toInt32(x) AS x,
    toInt32(y) AS y,
    toUInt8(intensity) AS v
FROM points
INTO OUTFILE 'points.png'
FORMAT PNG
SETTINGS output_format_image_width = 512, output_format_image_height = 512;

Animação

Se o resultado tiver uma coluna t de tipo inteiro, o formato produzirá um PNG animado (APNG) em vez de uma imagem estática. Os registros são agrupados em quadros com base no valor de t, que corresponde ao deslocamento temporal relativo do quadro. Cada quadro é uma imagem independente: a tela fica vazia no início de cada quadro e, no modo de coordenadas implícitas, o cursor reinicia no canto superior esquerdo. A coluna t pode ser combinada com qualquer um dos modos de coordenadas.

A unidade de t é definida por output_format_image_time_multiplier_seconds e output_format_image_time_divisor_seconds: uma unidade de t equivale a output_format_image_time_multiplier_seconds / output_format_image_time_divisor_seconds segundos. Com os valores padrão (1 e 60), uma unidade de t equivale a 1/60 de segundo.

Um quadro é exibido até o início do próximo quadro, portanto sua duração é a diferença entre dois valores consecutivos de t. O último quadro é exibido pelo mesmo tempo que o quadro anterior. A animação se repete indefinidamente.

SELECT
    number % 60 AS t,
    toInt32(intDiv(number, 60) % 64) AS x,
    toInt32((number * 7) % 64) AS y,
    toUInt8(255) AS v
FROM numbers(60 * 64)
INTO OUTFILE 'animation.png'
FORMAT PNG
SETTINGS output_format_image_width = 64, output_format_image_height = 64;

Transmissão de quadros

Por padrão, todos os quadros são coletados na memória e gravados ao final da consulta, mantendo um buffer de imagem para cada valor distinto de t e permitindo que t chegue em qualquer ordem.

A configuração output_format_image_streaming_animation grava cada quadro assim que o próximo valor de t é recebido. Apenas um buffer de imagem é mantido na memória, e os quadros chegam à saída enquanto a consulta ainda está em execução, permitindo que um visualizador os exiba à medida que são produzidos. Em contrapartida:

  • t deve ser não decrescente; caso contrário, a consulta lança uma exceção. Adicione ORDER BY t se necessário.
  • O número de quadros não é conhecido quando o cabeçalho precisa ser gravado; portanto, o fragmento acTL declara um limite superior em vez da contagem exata. Os navegadores reproduzem esse arquivo, mas decodificadores que confiam na contagem declarada (por exemplo, Pillow e algumas ferramentas APNG de linha de comando) relatam um erro após o último quadro real. Uma animação de um único quadro é a exceção: todo o resultado já foi lido quando esse quadro é gravado; portanto, a contagem é declarada com exatidão e a saída está em conformidade com a especificação.

Como um protocolo de imagem no terminal em linha transporta todo o fluxo de dados em um único payload, os quadros não podem chegar antecipadamente ao terminal, e essa configuração afeta apenas a quantidade de memória usada nesse caso. A contagem exata de quadros é corrigida no payload armazenado em buffer antes do envio; portanto, a ressalva sobre o limite superior não se aplica.

Uma animação é exibida apenas no modo de terminal iterm. O protocolo sixel não consegue representar uma animação, e o protocolo gráfico Kitty só anima por meio de um fluxo separado de comandos por quadro, não por meio de um fluxo de dados animado; portanto, exibiria apenas o primeiro quadro. Ambos os modos rejeitam um resultado com uma coluna t.

Exibindo imagens no terminal

Por padrão, o formato PNG grava os bytes brutos da imagem. A configuração output_format_image_terminal_mode faz com que a imagem seja renderizada diretamente no terminal usando um protocolo de imagem no terminal em linha:

Valor Comportamento
`` (vazio) Grava os bytes brutos da imagem (padrão).
iterm Usa o protocolo de imagem embutida do iTerm2.
kitty Usa o protocolo gráfico do Kitty. Não é possível exibir uma animação.
sixel Usa o protocolo Sixel. A imagem é reduzida a uma paleta fixa de 6×6×6, e o canal alfa, se houver, é composto sobre um fundo preto.
auto Se a saída for um terminal, detecta suas capacidades e usa iterm, kitty ou sixel (nessa ordem); caso contrário, grava os bytes brutos da imagem.
SELECT toUInt8(x * 25) AS r, toUInt8(y * 25) AS g, toUInt8((x + y) * 12) AS b
FROM (SELECT number % 10 AS x, intDiv(number, 10) AS y FROM numbers(100))
FORMAT PNG
SETTINGS output_format_image_width = 10, output_format_image_height = 10, output_format_image_terminal_mode = 'auto';

Configurações de formato

Configuração Descrição Padrão
output_format_image_width Largura da imagem de saída, em pixels. 1024
output_format_image_height Altura da imagem de saída, em pixels. 1024
output_format_image_terminal_mode Protocolo de imagem no terminal em linha (veja acima). `` (vazio)
output_format_image_time_multiplier_seconds Numerador da unidade de tempo da coluna t, em segundos. 1
output_format_image_time_divisor_seconds Denominador da unidade de tempo da coluna t, em segundos. 60
output_format_image_streaming_animation Grave cada quadro assim que t avançar (veja acima). 0
Navigation