5.7. Composição de imagens¶
As primitivas de desenho da página anterior pintam marcas geométricas numa imagem – uma linha, um retângulo, um fragmento de texto. Isso cobre a maior parte das anotações que um algoritmo precisa de tornar visíveis, mas não todas. Por vezes a anotação é em si mesma uma imagem: um fotograma de referência capturado para mostrar lado a lado com o atual, uma miniatura de uma captura anterior apresentada num canto da pré-visualização, ou um modelo previamente armazenado visualizado sobre um fotograma em direto para calibração. O mecanismo para desenhar uma imagem sobre outra é um único método – draw_image() – com parâmetros suficientes para gerir a posição, o escalonamento, a paleta de cores e a transparência que uma composição real necessita.
5.7.1. A chamada básica¶
Na sua forma mais simples, draw_image recebe outra Image e uma posição onde desenhá-la:
reference = image.Image("/sdcard/reference.bmp")
img.draw_image(reference, x=10, y=10)
O destino é img; a fonte é reference; o pixel superior esquerdo da fonte fica em (10, 10) de img, e os restantes pixels da fonte seguem para a direita e para baixo a partir daí. Os pixels do destino que a fonte cobre são substituídos pelos pixels correspondentes da fonte; os pixels fora da área da fonte ficam intocados.
Se a fonte ultrapassar o limite do destino, as partes que ficam de fora são silenciosamente cortadas – o mesmo comportamento tolerante que set_pixel apresenta para posições fora do intervalo. O código da aplicação não tem de limitar a posição às dimensões da imagem antecipadamente; pode passar a posição desejada e deixar que o método trate do corte.
5.7.2. Carregamento de ficheiro inline¶
draw_image aceita um caminho de ficheiro em vez do argumento Image e carrega o ficheiro antes de o compor:
img.draw_image("/sdcard/reference.bmp", x=10, y=10)
Parece uma conveniência – uma linha em vez de duas – e é-o, mas a diferença é mais do que sintaxe. Construir uma Image a partir de um ficheiro aloca um buffer para guardar os pixels descodificados, e esse buffer subsiste até que o recolhedor de lixo o liberte. Passar o caminho diretamente para draw_image permite que o módulo descodifique o ficheiro num buffer temporário, componha a partir dele e liberte o buffer quando a chamada retorna, sem que o código da aplicação tenha de manter uma referência a uma Image separada entre fotogramas.
5.7.3. Escalonamento¶
Quando a fonte e o destino têm tamanhos diferentes – uma captura de baixa resolução a ser composta sobre uma tela de maior resolução, ou uma miniatura que precisa de ser dimensionada para uma determinada fração do fotograma – dois parâmetros de escala tratam do redimensionamento da fonte à medida que é desenhada:
img.draw_image(reference, x=10, y=10, x_scale=2.0, y_scale=2.0)
x_scale e y_scale são floats independentes; passar ambos com o mesmo valor escala uniformemente, e passar valores diferentes estica ou encolhe a fonte ao longo de um eixo. O escalonamento ocorre no momento do desenho; a fonte reference não é modificada.
Uma máscara de bits de flags de dica decide como o escalonamento interpola entre pixels. image.BILINEAR produz resultados mais suaves ao custo de mais computação; image.BICUBIC produz resultados ainda mais suaves e custa mais; o padrão usa o vizinho mais próximo, que é o mais económico e a escolha certa quando a fonte já está na resolução de pixel do destino. As flags de gestão de aspeto – SCALE_ASPECT_KEEP, SCALE_ASPECT_EXPAND, SCALE_ASPECT_IGNORE – decidem o que fazer quando a proporção da fonte não corresponde ao retângulo em que está a ser desenhada.
5.7.4. Mistura alfa¶
Por defeito, draw_image substitui os pixels do destino pelos pixels da fonte. Quando o objetivo é uma sobreposição translúcida – para que o destino apareça através da fonte – o parâmetro alpha controla como os dois são misturados. alpha=0 mostra apenas o destino (sem fonte); alpha=255 é o padrão e mostra apenas a fonte (substituição total); valores intermédios misturam os dois proporcionalmente:
img.draw_image(overlay, x=0, y=0, alpha=128)
O argumento separado alpha_palette é o único mecanismo de alfa por pixel do módulo. Recebe uma imagem GRAYSCALE cujos valores são usados como alfa na posição correspondente na fonte – um mapa de calor cujo alfa varia com a sua intensidade, por exemplo. O alfa tem de ser fornecido como esse argumento em escala de cinzentos separado; uma imagem fonte que tenha o seu próprio canal alfa (um PNG com transparência, por exemplo) não o traz automaticamente.
5.7.5. ROI da fonte e paleta¶
Dois parâmetros adicionais completam o mecanismo de composição:
roi=(x, y, w, h)restringe a fonte a um sub-retângulo de si mesma, de forma a que apenas esse retângulo seja composto sobre o destino. Útil para cortar dentro da mesma chamada, sem preparar um intermediário cortado.color_palettesubstitui o valor de cada pixel da fonte através de uma tabela de consulta antes de desenhar – o mesmo mecanismo queto_rainbow()eto_ironbow()usam, exposto aqui para que uma sobreposição possa ser paletizada no caminho para o destino sem uma passagem de conversão separada.
Ambos compõem com tudo o mais na chamada: o escalonamento, o alfa, o argumento mask do lado do destino e o parâmetro roi do lado do destino que limita a escrita a um retângulo do destino.