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:
<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}" />
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 < 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!