Manipulação de imagem com JSF 2.0 [RESOLVIDO]

Estou fazendo um componente JSF para manipulação de imagem.
O usuário vai ter que dar upload, esta imagem vai passar por vários algoritmos para tentar reduzir o tamanho(em bytes), e depois terei que apresentar na tela.
O problema é que os algoritmos que eu tenho eles usam um formato de imagem diferente que o JSF me trás.
Para o JSF eu tenho que trabalhar com StreamedContent, e eu manipulo a imagem com o formato java.awt.Image.
Converter o InputStream para Image, estou conseguindo com o código abaixo:

public InputStream removeColorImage(InputStream image){ BufferedImage bf = ImageIO.read(image); Image i = Toolkit.getDefaultToolkit().createImage(bf.getSource());
Agora para fazer o contrario, converter de Image para InputStream é o problema.

Axo q n tem como passar diretamente para um inputstream, talvez tenha q criar

Espero q isso ajude:

crie a classe MeuStream, q sera usado para armazenar e criar o inputstream:

[code]package p252718;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

public class MeuStream extends OutputStream {

private List<Integer> dados = new LinkedList<Integer>();

@Override
public void write(int b) throws IOException {
    dados.add(b);
}

public InputStream criarInputStream() {
    return new MeuInputStream(dados.iterator(), dados.size());
}

private class MeuInputStream extends InputStream {

    private Iterator<Integer> buffer;
    private int qtd;

    private MeuInputStream(Iterator<Integer> iterator, int size) {
        buffer = iterator;
        qtd = size;
    }

    @Override
    public int read() throws IOException {
        if (qtd == 0) {
            return -1;//por padrao significa q n tem mais bytes
        } else {
            qtd--;
            return buffer.next();
        }
    }

    @Override
    public int available() throws IOException {
        return qtd;
    }
}

}
[/code]

depois use:

MeuStream ms = new MeuStream(); ImageIO.write(bufferedImage, "nome.(gif,png ou jpg)", ms); InputStream is = ms.criarInputStream();

n sei se vai funcionar, talvez de problemas com relacao ao tipo, entao tente mudar a lista de Integer para Byte

Bem… eu estou usando o FileUpload do PrimeFaces que me da o conteúdo da imagem em byte[]. Depois eu converto para Image, faço um tratamento (basicamente eu reduzo ela para gerar um thumbnail), então eu trago de volta para byte[], crio um ByteArrayInputStream e disso eu gero o StreamedContent para mostrar no p:graphicImage do PrimeFaces.
Se quiser, posso te passar o código depois (está no meu notebook).

Tentei implementar a classe que você passou, mas não deu certo, mesmo eu mudando o tipo da lista para byte.

Estou com problema na parte da conversão de Image para byte[], como você está fazendo?

para converter Image em bytes

[code] //Converte Image para BufferedImage
Image i = imagem;
BufferedImage bi = new BufferedImage(i.getWidth(null), i.getHeight(null), BufferedImage.TYPE_INT_RGB);//BufferedImage.TYPE_INT_ARGB, com valor alpha
Graphics2D g2d = bi.createGraphics();
g2d.drawImage(i, 0, 0);
g2d.dispose();

    //Grava o tamanho no stream
    //outputStream.write(bi.getWidth());
    //outputStream.write(bi.getHeight());
    byte[] buffer = new byte[3];//4 se for ARGB
    Color c;
    for (int x = 0; x < bi.getWidth(); x++) {
        for (int y = 0; y < bi.getHeight(); y++) {
            c = new Color(bi.getRGB(x, y));
            buffer[0] = (byte) c.getRed();
            buffer[1] = (byte) c.getGreen();
            buffer[2] = (byte) c.getBlue();
            //buffer[3] = (byte) c.getAlpha(); //ARGB
            //buffer contendo RGB em bytes de um pixel
            outputStream.write(buffer);
        }
    }[/code]

Não estou conseguindo implementar este seu exemplo, será que poderia explicar melhor?

Obrigado.

Olha só. Usei o primefaces para o file upload, da seguinte forma:

&lt;p:fileUpload fileLimit="10" fileUploadListener="#{administracao.handleFileUpload}" mode="advanced" update="info" multiple="true" sizeLimit="5242880" allowTypes="/(\.|\/)(gif|jpe?g|png)$/" fileLimitMessage="#{msg.fileUploadErroLimite}" cancelLabel="#{msg.fileUploadCancelarLabel}" invalidFileMessage="#{msg.fileUploadErroArquivoInvalido}" invalidSizeMessage="#{msg.fileUploadErroLimite}" label="#{msg.fileUploadChooseLabel}" /&gt;

Então eu pego o conteudo (byte[]) e salvo em um bean de Imagem.

public void handleFileUpload(FileUploadEvent event){
	UploadedFile item = event.getFile();
	for(Imagem img : getNoticia().getImagens()){
		if(img.getNome().equals(item.getFileName())){
			String[] params = new String[1];
			params[0] = img.getNome();
			FacesContextUtil.setMensagemErro(&quot;fileUploadArquivoExiste&quot;, formSettings.getLocalAtual(), FacesMessage.SEVERITY_WARN, params);
			return;
		}
	}
	Imagem imagem = new Imagem();
	imagem.setLength(new Long(item.getContents().length));
	imagem.setNome(item.getFileName());
	imagem.setArquivo(item.getContents());
	imagem.setData(new Date());
	imagem.setMime(item.getContentType());
	noticia.getImagens().add(imagem);
}

Esse ‘arquivo’ é do tipo ‘byte[]’.

Então eu tenho um método para criar o thumbnail, retornando byte[], da seguinte forma:

public byte[] getThumbnail(){
	ImageIcon imageIcon = new ImageIcon(arquivo);
	Image inImage = imageIcon.getImage();
	double scale = (double) MAX_THUMBNAIL_WIDTH / (double) inImage.getWidth(null);
	
	int scaledW = (int) (scale * inImage.getWidth(null));
	int scaledH = (int) (scale * inImage.getHeight(null));
	
	BufferedImage outImage = new BufferedImage(scaledW, scaledH, BufferedImage.TYPE_INT_RGB);
	
	AffineTransform tx = new AffineTransform();
	if(scale &lt; 1.0d){
		tx.scale(scale, scale);
	}
	
	Graphics2D g2d = outImage.createGraphics();
	g2d.drawImage(inImage, tx, null);
	g2d.dispose();
	
	ByteArrayOutputStream baos = new ByteArrayOutputStream();
	try {
		ImageIO.write(outImage, mime.substring(6), baos);
		return baos.toByteArray();
	} catch (IOException e) {
		e.printStackTrace();
	}
	finally{
		try {
			baos.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	return null;
}

Sendo que ‘MAX_THUMBNAIL_WIDTH’ é uma variável ‘final’ com a quantidade de pixels q eu quero meu thumbnail (no caso, está 100).

[code]
public byte[] toBytes(Image imagem) {
ByteOutputStream outputStream = new ByteOutputStream();//cria um outputstream

    Image i = imagem;//variavel auxiliar
    BufferedImage bi = new BufferedImage(i.getWidth(null), i.getHeight(null), BufferedImage.TYPE_INT_RGB);//BufferedImage.TYPE_INT_ARGB, com valor alpha // cria um buffer para edicao
    Graphics2D g2d = bi.createGraphics();//obtem um "editor grafico"
    g2d.drawImage(i, 0, 0, null);//pinta o buffer com a imagem
    g2d.dispose();//finaliza o "editor grafico"

    //Grava o tamanho no stream, se achar necessario, depende de como sera usado o inputstream
    //outputStream.write(bi.getWidth());  
    //outputStream.write(bi.getHeight()); 

    byte[] buffer = new byte[3];//4 se for ARGB  //cria um buffer de 1 pixel
    Color c;//variavel auxiliar

    for (int x = 0; x < bi.getWidth(); x++) {//loop para correr no eixo x
        for (int y = 0; y < bi.getHeight(); y++) {//loop para correr no eixo y
            c = new Color(bi.getRGB(x, y));//cria uma cor para conversao em bytes
            buffer[0] = (byte) c.getRed();//obtem a cor vermelha
            buffer[1] = (byte) c.getGreen();//obtem a cor verde
            buffer[2] = (byte) c.getBlue();//obtem a cor azul
            //buffer[3] = (byte) c.getAlpha(); //ARGB  //obtem o alpha
            //buffer contendo RGB em bytes de um pixel  
            outputStream.write(buffer);//escreve no stream
        }
    }
    outputStream.close();
    return outputStream.getBytes();//retorna em bytes
    //return outputStream.newInputStream(); //retorna o inputstream

}[/code]

ou melhor ainda

ByteOutputStream outputStream = new ByteOutputStream(); ImageIO.write(suaImagem, "nomedaimagem.(png, jpg ou gif)", outputStream );//necessario indicar a extensao se png, gif ou jpg outputStream.close(); InputStream ip = outputStream.newInputStream();//obtem o inputStream byte[] imagemEmBytes = outputStream.getBytes();//obtem em bytes

no trecho seguinte do fernando.camargo, a imagem é redimensionada

[code] double scale = (double) MAX_THUMBNAIL_WIDTH / (double) inImage.getWidth(null);

int scaledW = (int) (scale * inImage.getWidth(null));  
int scaledH = (int) (scale * inImage.getHeight(null));  
  
BufferedImage outImage = new BufferedImage(scaledW, scaledH, BufferedImage.TYPE_INT_RGB);  
  
AffineTransform tx = new AffineTransform();  
if(scale < 1.0d){  
    tx.scale(scale, scale);  
}

.
.
.
.
g2d.drawImage(inImage, tx, null); [/code]

Obrigado, problema resolvido!