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

8 respostas
F

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.

8 Respostas

C

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:
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;
        }
    }
}
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

F

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).

F

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?

C

para converter Image em bytes

//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);
            }
        }
F

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

Obrigado.

F

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("fileUploadArquivoExiste", 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).

C
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
}
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
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);
F

Obrigado, problema resolvido!

Criado 15 de setembro de 2011
Ultima resposta 16 de set. de 2011
Respostas 8
Participantes 3