Estou procurando a maneira mais rápida de obter dados de pixel (int o formulário int[][]
) de a BufferedImage
. Meu objetivo é ser capaz de endereçar o pixel (x, y)
da imagem usando int[x][y]
. Todos os métodos que encontrei não fazem isso (a maioria deles retorna int[]
s).
java
bufferedimage
javax.imageio
ryyst
fonte
fonte
getRGB
esetRGB
diretamente?getRGB
esetRGB
diretamente.Respostas:
Eu estava brincando com esse mesmo assunto, que é a maneira mais rápida de acessar os pixels. Atualmente, conheço duas maneiras de fazer isso:
getRGB()
método de BufferedImage conforme descrito na resposta de @tskuzzy.Acessando a matriz de pixels diretamente usando:
Se você estiver trabalhando com imagens grandes e o desempenho for um problema, o primeiro método não é absolutamente o melhor. O
getRGB()
método combina os valores alfa, vermelho, verde e azul em um int e retorna o resultado, que na maioria dos casos você fará o inverso para obter esses valores de volta.O segundo método retornará os valores de vermelho, verde e azul diretamente para cada pixel e, se houver um canal alfa, ele adicionará o valor alfa. Usar este método é mais difícil em termos de cálculo de índices, mas é muito mais rápido do que a primeira abordagem.
No meu aplicativo, consegui reduzir o tempo de processamento dos pixels em mais de 90% apenas mudando da primeira abordagem para a segunda!
Aqui está uma comparação que configurei para comparar as duas abordagens:
Você consegue adivinhar a saída? ;)
fonte
convertTo2DUsingGetRGB
econvertTo2DWithoutUsingGetRGB
. O primeiro teste leva em média 16 segundos. O segundo teste leva em média 1,5 segundos. No início, pensei que "s" e "ms" eram duas colunas diferentes. @Mota, ótima referência.BufferedImage
detype
, por exemploTYPE_INT_RGB
, ouTYPE_3BYTE_BGR
e punho de forma adequada. Esta é uma das coisas quegetRGB()
faz por você, que o torna mais lento :-(|=
vez de+=
combinar os valores no método 2?Algo assim?
fonte
BufferedImage
iria armazenar os pixels usando uma matriz 2D int, de qualquer maneira?Raster
buffer de dados do, o que é definitivamente uma coisa boa, já que resulta em punção de aceleração.Achei que a resposta de Mota me deu um aumento de velocidade de 10 vezes - então, obrigado Mota.
Eu embrulhei o código em uma classe conveniente que pega o BufferedImage no construtor e expõe um método getRBG (x, y) equivalente que o torna uma substituição para o código que usa BufferedImage.getRGB (x, y)
fonte
A resposta de Mota é ótima, a menos que seu BufferedImage veio de um Bitmap monocromático. Um Bitmap monocromático tem apenas 2 valores possíveis para seus pixels (por exemplo 0 = preto e 1 = branco). Quando um bitmap monocromático é usado, o
call retorna os dados brutos do Pixel Array de forma que cada byte contenha mais de um pixel.
Portanto, quando você usa uma imagem bitmap monocromática para criar seu objeto BufferedImage, este é o algoritmo que deseja usar:
fonte
Se for útil, tente isto:
fonte
Aqui está outra implementação FastRGB encontrada aqui :
O que é isso?
Ler uma imagem pixel a pixel através do método getRGB de BufferedImage é bastante lento, esta classe é a solução para isso.
A ideia é que você construa o objeto alimentando-o com uma instância BufferedImage, e ele lê todos os dados de uma vez e os armazena em um array. Quando você deseja obter pixels, chame getRGB
Dependências
Considerações
Embora FastRGB torne a leitura de pixels muito mais rápida, pode levar a um alto uso de memória, pois simplesmente armazena uma cópia da imagem. Portanto, se você tiver um BufferedImage de 4 MB na memória, depois de criar a instância FastRGB, o uso da memória será de 8 MB. No entanto, você pode reciclar a instância BufferedImage depois de criar o FastRGB.
Tenha cuidado para não cair em OutOfMemoryException ao usá-lo em dispositivos como telefones Android, onde RAM é um gargalo
fonte
Isso funcionou para mim:
fonte
i
?