Como criar uma subclasse de BufferedImage?

Pessoal,

Estou trabalhando com imagens e gostaria de criar uma classe Imagem, que é subclasse de BufferedImage. A classe BufferedImage recebe no construtor 3 parâmetros.
Eu tenho um leitor de imagens, que lê as imagens no disco. Agora, na classe imagem, o construtor fica assim:

public Imagem() {
  super(0, 0, 0);
}

O que é errado, porque diz que a imagem tem 0 de altura, largura e não tem tipo.
Só que como vou saber o tamanho da imagem se eu só sei o tamanho dela em tempo de execução? Resumindo, como saber quais parâmetros eu devo passar?

[editado]
Outra coisa que pensei em fazer pra facilitar é ter uma referência de BufferedImage em Imagem, mas aparentemente não faz sentido porque uma Imagem não tem outra, certo?

Pode facilitar agora, mas depois, será que posso ter algum trabalho maior?
[/editado]

Abraço.

De repente é esse o caso. Será que composição não cairia melhor que a herança nesse caso ?

Também acho preferível usar composição no lugar de herança.
Até porque, a classe ImageIO vai carregar BufferedImages do disco, e não terá como você converte-las para a sua classe.

Aliás, o que você quer inserir a mais na imagem?

Pois é… Eu estou usando composição mesmo.

ViniGodoy,
Não é bem inserir. Eu estou tentando fazer algumas classes que sejam reutilizáveis para o meu TCC, ano que vem. Quero providenciar todo tipo de operações que eu possa fazer do modo mais simples possível, de modo que eu não precise ficar escrevendo muita linha de código. Aí, se eu terminar essa parte, não terei tanto código pra escrever mais tarde, sabe como?

Também estou fazendo isso pra pegar a matriz uni e bidimensional dos pixels. Aí a classe Imagem teria isso. Também algumas operações, como colorir alguns pixels e transformar a imagem pra grayscale vão ser implementadas ainda nas férias, pra que ano que vem eu não precise me preocupar com isso (quero fazer o máximo possível nas férias pra que ano que vem eu só me preocupe com as técnicas).

Eu até estou pesando em usar a JAI, mas ainda não analisei isso direito.

Abraço.

A classe da imagem já tem métodos para isso… Já viu o getRaster()? Procura no Google por “Java Boutique Raster” que vem duas matérias ótimas sobre o assunto.

Quanto ao GrayScale, eu recomendo que você dê uma olhada aqui:
http://www.jhlabs.com/ip/filters/index.html

ViniGodoy,

Muito obrigado. Mais uma vez, sempre ajudando o pessoal.

Eu sei do getRaster() (não sei o que significa Raster e Band). Você conhece algum artigo bom sobre isso?

Eu gostaria de fazer a classe Imagem pra encapsular (eu acho). Por exemplo, eu vi uma apresentação que dizia como pegar a matriz de pixels, mas era uma matriz unidimensional, que pegava os pixels através da multiplicação da linha pela coluna pelo band (que eu ainda não sei o que é). Aí queria trabalhar como se fosse uma matriz bidimensional, sabe como?

Esse que indiquei ali em cima mesmo:
http://javaboutique.internet.com/tutorials/rasters/
http://javaboutique.internet.com/tutorials/rasters2/

O raster já te dá uma maneira bidimensional para acessar a imagem.

O negócio da multiplicação é mais simples que parece. Se você teum um array assim:

public int pixels = {1,2,3,4,5,6,7,8,9};

Você pode acessa-lo de maneira bidimensional. Sua imagem tem, hipotéticamente, 3x3 pixels, você poderia acessar esse array unidimensional como um bidimensional través da seguinte conta:
linha*3+coluna

Desde que a linha e a coluna iniciassem em 0. Muitas vezes vc usa esse artificio para acessar uma imagem BGR como RGB. Note que para fazer esse tipo de inversão, bastaria alterar um pouco essa conta para linha*3+(3-coluna)

Hmmm. Pois é.
Você sabe por que não deixam como uma matriz bidimensional mesmo (usando [][])? Eu ainda prefiro lidar com linha e coluna em “índices separados”, sabe como? Acho que é mais fácil e legível.

Aproveitando o gancho, queria perguntar uma coisa. Dada uma imagem colorida, eu posso pegar o RGB, certo? Inclusive, tem até método pra isso eu acho (pra pegar um int) e depois ir jogando pra vermelho, verde e azul (usando algumas coisas estranhas como 0x0000FF00>>>16 (ou 8)). O melhor, pra separar o RGB (vale a pena fazer isso) é colocar os 3 em uma String ou fazer três matrizes diferentes?

Abraço.

Essas coisas estranhas variam de acordo com o tipo de imagem que você está trabalhando. Alguns tipos não tem 8 bits para cada componente de cor. Aí tudo fica mais estranho ainda. Eu publiquei um artigo no meu blog que fala como a SDL trabalha com o assunto. Tem muita coisa sobre esses deslocamentos lá.

O cálculo ocorre para vc não precisar gerar um novo array para a imagem, só para inverter os componentes de cor. Imagens podem ser muito grandes (algumas tem vários MB de tamanho), então não é tão fácil assim vc criar um novo array (que também vai alocar os mesmos vários MB) e copiar os bytes na ordem certa. Fora que, geralmente, vc carrega e salva no mesmo formato, o que forçaria vc a “desinverter” a ordem dos bytes novamente.

ViniGodoy,

Então você acha que o melhor seria usar mesmo o vetor unidimensional, certo?

Abraço.

Um outro detalhe, relativo a desempenho: se você deixa os componentes de cor em 3 matrizes diferentes, vai ter problemas de “cache” de memória quando tiver imagens relativamente grandes (alguns MB, dependendo do tamanho do cache do processador), uma vez que você estará acessando regiões de memória não-contíguas - estou supondo que você esteja acessando as N cores mais ou menos ao mesmo tempo.

Isto por acaso seria devido as tecnicas de swap registrador/memoria ?

thingol,

Então você concorda que usar uma matriz de String seria melhor?

luistiagos,

Eu responderia “Provavelmente” :).

Abraço.