Pergunta

Eu tenho uma variedade de bytes representando uma imagem no formato BMP do Windows e gostaria que minha biblioteca a apresentasse ao aplicativo Java como um BufferedImage, sem copiando os dados do pixel.

O principal problema é que todas as implementações de Raster Nos pixels da imagem da loja JDK em ordem de cima para baixo, da esquerda para a direita, enquanto os dados do Pixel BMP são armazenados de baixo para cima, da esquerda para a direita. Se isso não for compensado, a imagem resultante será invertida verticalmente.

A "solução" mais óbvia é definir o SampleModel's scanlineStride propriedade para um valor negativo e alterar as compensações da banda (ou o DataBufferOffset da matriz) para apontar para o pixel superior esquerdo, ou seja, o primeiro pixel da última linha da matriz. Infelizmente isso não funciona porque todo o SampleModel Os construtores lançam uma exceção se receber um negativo scanlineStride argumento.

Atualmente estou trabalhando em torno disso, forçando o scanlineStride Campo para um valor negativo usando reflexão, mas eu gostaria de fazê -lo de maneira mais limpa e portátil, se possível. por exemplo, há outra maneira de enganar o Raster ou SampleModel Arranjar os pixels em ordem de baixo para cima, mas sem quebrar o encapsulamento? Ou existe uma biblioteca em algum lugar que envolverá o Raster e SampleModel, apresentando as linhas de pixel em ordem inversa?

Eu preferiria evitar as seguintes abordagens:

  • Copiando toda a imagem (por razões de desempenho. O código deve processar centenas de imagens grandes (> = 1mpixels) por segundo e, embora toda a imagem deva estar disponível para o aplicativo, ela normalmente acessará apenas um pequeno (mas difícil de predeus ) parte da imagem.)
  • Modificando o DataBuffer Para realizar a transformação de coordenadas (isso realmente funciona, mas é outra solução "suja", porque o buffer não precisa saber sobre o layout de scanline/pixel.)
  • Reimplementar o Raster e/ou SampleModel Interfaces do zero (devido à maneira como a verificação de compatibilidade é implementada (pelo menos no Sun JDK), exigindo subclasses específicas de SampleModel Então, um genérico BottomUpSampleModel A classe Wrapper não funcionaria.)
Foi útil?

Solução

Eu descobri que posso implementar isso usando apenas uma nova classe, que eu nomeei BottomUpComponentSampleModel. Ele se estende ComponentSampleModel e nega o valor do scanlineStride campo (que, felizmente, é protected ao invés de private) depois de chamar o construtor de superclasse. Todos os cálculos de endereço do pixel funcionam bem, embora a validação em Raster.createWritableRaster Não (isso pode deixar de detectar se você fornece uma matriz muito pequena), mas isso não é um problema sério.

Isso não é necessário com MultiPixelPackedSampleModel ou SinglePixelPackedSampleModel, como eles aceitam um negativo scanlineStride. Eles não têm compensações de banda, mas isso pode ser contornado definindo um compensado no DataBuffer.

Outras dicas

Que tal ter o aplicativo (ou camada de acesso) a tradução e o fliping funcionam em sua cópia ao acessar a parte minúscula (mas difícil de predito) da imagem?

Melhor ainda, parece que o aplicativo não precisa exibir a imagem? Por que se preocupar em querer virá -lo em primeiro lugar para que pareça correto na tela? Basta escrever a lógica para trabalhar na versão que você tem? Também não há necessidade de ter um bufferImage, trabalhe diretamente na matriz.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top