Pessoal ,
estou utilizando uma classe pronta para gerar miniaturas de imagens , porem quero modificar o local de escrita desse novo arquivo q é gerado.
Alguem pode me ajudar?
esse e o codigo
/*
* Miniatura.java
*
* Created on 30 de Março de 2007, 15:33
*
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
*/
package bean;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.Locale;
import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.plugins.jpeg.JPEGImageWriteParam;
import javax.imageio.stream.ImageOutputStream;
import javax.imageio.ImageIO;
/**
*
* @author renan
*/
public class Miniatura {
/** Creates a new instance of Miniatura */
public Miniatura() {
}
private double widthFile = 0;
private double heightFile = 0;
private int width, height;
public void compressJpegFile(File infile, File outfile,float compressionQuality,int widthCanvas,int heightCanvas)
throws IOException {
// Retrieve jpg image to be compressed
BufferedImage rendImage = ImageIO.read(infile);
widthFile = rendImage.getWidth();
heightFile = rendImage.getHeight();
double aspectRatioCanvas = widthCanvas/heightCanvas;
double aspectRatioFile = widthFile/heightFile;
widthFile = widthCanvas;
heightFile = widthCanvas/aspectRatioFile;
if(heightFile>heightCanvas){
heightFile = heightCanvas;
widthFile = heightCanvas*aspectRatioFile;
}
this.width = (int)widthFile;
this.height = (int)heightFile;
ImageTypeSpecifier its = ImageTypeSpecifier.createFromRenderedImage(rendImage);
BufferedImage outImage = its.createBufferedImage(width, height);
Graphics2D graphics2D = outImage.createGraphics();
graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
// graphics2D.drawRenderedImage(rendImage, new AffineTransform());
graphics2D.drawImage(rendImage, 0, 0, width, height, null);
// Find a jpeg writer
ImageWriter writer = null;
Iterator iter = ImageIO.getImageWritersByFormatName("jpg");
if (iter.hasNext()) {
writer = (ImageWriter)iter.next();
}
// Prepare output file
ImageOutputStream ios = ImageIO.createImageOutputStream(outfile);
writer.setOutput(ios);
// Set the compression quality
ImageWriteParam iwparam = new JPEGImageWriteParam(Locale.getDefault());
iwparam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT) ;
iwparam.setCompressionQuality(compressionQuality);
// Write the image
writer.write(null, new IIOImage(outImage, null, null), iwparam);
//infile.delete();
// Cleanup
ios.flush();
writer.dispose();
ios.close();
// return
}
public int getLargura(){
return width;
}
public int getAltura(){
return height;
}
}
O segundo parâmetro (File outfile) é onde você vai jogar os arquivos. Leia a documentação da classe java.io.File para ver o que você precisa (por exemplo, como selecionar o diretório usando essa classe).
Eu consigo mudar o local, mas eu nao quero que salve nesse local… eu quero que esse metodo compressJpegFile() me retorne um file com a miniatura , mas eu nao sei como faco jogar essa imagem redimensionada para dentro de um FILE para que eu possa retornar…
java.io.File representa apenas o diretório e nome do arquivo. Um “File” não é mais que isso.
O arquivo em si pode ser obtido com um FileInputStream (para leitura), FileOutputStream (para escrita), ou RandomAccessFile (para leitura e escrita).
Provavelmente você está querendo que a tal imagem fique persistida em memória em vez de você ter de inventar um nome de arquivo temporário, mas aí você precisa ler a documentação da Java ImageIO para ver se isso é possivel.
Não sei se expliquei direito , neste meu código eu passo um arquivo com a imagem para o metodo compressJpegfile e ele escreve um novo arquivo para mim com a imagem redimensioanda.
Só que eu nao quero que ele escreva, quero apenas q redimensione a imagem , crie um file em memoria para que eu possa fazer upload dessa imagem redimensionada.
Entendem?? nao sei se dá pra fazer isso …
Se alguem souber uma maneira de eu redimensionar uma imagem em memoria e fazer upload dela sem ter q ‘escrever’ ela fisicamente.
???
aguardo respostas… vlw
Basta gerar uma nova BufferedImage, com o conteúdo da primeira redimensionado e retransmitir essa nova BufferedImage. Você não é obrigado a grava-la. O método ImageIO.write aceita qualquer OutputStream, e isso inclui o de um Socket/Servlet.
mas na verdade eu queria retornar já um File… para poder enviar…
como faço para desse BufferedImage passar para um File ?
Acho que você está confundindo algum conceito.
O que seria o file de uma BufferedImage? Uma imagem gravada no disco.
Mas você não quer gravar no disco… então, não pode ter um file.
A grande questão é. Como você envia esse file? Através do OuputStream de algum socket ou servlet, não estou certo?
Então, por que ao invés de usar um FileOutputStream para ler de um arquivo e enviar para o socket/servlet, você não usa o ImageIO.write para escrever diretamente nesse mesmo OutputStream?
O único detalhe adicional é que você também terá que mandar o formato da imagem, além do nome. Pois o ImageIO.read do outro lado precisará dessa informação.
Você não entendeu ainda?
Um java.io.File não é um arquivo, nem um objeto de memória.
Ele é apenas o nome do arquivo e do diretório.
O nome é muito enganador (java.io.File não deveria ser um arquivo? Mas não é!).
Se você precisa mandar o arquivo de volta por uma aplicação Web, não pode usar um File, e sim pegar o OutputStream do objeto servlet, como o ViniGodoy lhe disse.
A sua classe que você mostrou terá de ser ligeiramente modificada, não dá para usar como está.
to comecando a entender…
entao essa minha classe vai retornar o bufferedImage ??
o problema e que nesse metodo… ele cria a miniatura , eu pego essa miniatura já como file jogo dentro de um lista(porque gero duas) .
public ArrayList<File> criaMiniatura(File file){
ArrayList<File> listaFile = new ArrayList<File> ();
String nome = null;
String extensao=null;
StringTokenizer st= new StringTokenizer(file.getName(),".");
if(st.hasMoreTokens()){
nome=st.nextToken();
}
while(st.hasMoreTokens()){
extensao=st.nextToken();
}
try {
//cria miniatura pequena
File fileminip = new File(nome+"_THN_P."+extensao);
Miniatura minip = new Miniatura();
minip.compressJpegFile(file,fileminip,1.0f,150,113);
listaFile.add(fileminip);
//cria miniatura grande
File fileminig = new File(nome+"_THN_G."+extensao);
Miniatura minig = new Miniatura();
minig.compressJpegFile(file,fileminig,1.0f,270,203);
listaFile.add(fileminig);
} catch (IOException ex) {
ex.printStackTrace();
}
return listaFile;
}
daí entao pego essa lista de files e mando pro metodo q envia os arquivos
public boolean enviaArquivo(ArrayList<File> listafile, int tipo) throws FileNotFoundException, IOException{
String caminhoDir = null;
File property = new File("propertyProjeto.properties");
Properties props = new Properties();
FileInputStream fis = null;
fis = new FileInputStream(property);
props.load(fis);
fis.close();
if(tipo==1){
caminhoDir= props.getProperty("diretorioImagem");
}else if (tipo==2){
caminhoDir= props.getProperty("diretorioVideo");
}else if (tipo==3){
caminhoDir=props.getProperty("diretorioAnimacao");
}
File caminho = new File(caminhoDir);
// Mandar o arquivo para o diretório upload
for(int i=0; i<listafile.size(); i++){
File arq = new File(caminho,listafile.get(i).getName());
InputStream is,input;
FileOutputStream fos = new FileOutputStream(arq);
is = new FileInputStream(listafile.get(i));
byte[] buffer = new byte[2048];
int nLidos;
while ((nLidos = is.read(buffer)) >= 0) {
fos.write(buffer, 0, nLidos);
}
fos.flush();
fos.close();
listafile.get(i).delete();
}
entao eu teria que mudar os tres metodos…
Se você quer parar de salvar, vai ter que parar de trabalhar com files e passar a trabalhar com as imagens e outpustreams diretamente.
Simples assim.
E sim, isso implica a alterar todos os métodos.
beleza… entao vamos lá??
esse metodo compressJpegFile… pra eu retornar a imagem redimensionada eu retorno o BufferedImage??
Não sei, não conheço a classe Miniatura ou os requisitos do seu sistema.
O fato é, para se trabalhar sem salvar, você deverá trabalhar apenas com BufferedImages, o tempo todo. A classe miniatura deveria encapsular os redimensionamentos ou coisa do tipo. Parece-me que é o que ele faz, já que o método de compressão está lá.
Gostaria que você explicasse melhor qual é o seu problema.
a) Você tem uma aplicação Web ou Desktop?
b) Se for uma aplicação Web, como você está pensando em estruturar sua página? Lembre-se que uma página JSP só pode gerar um componente (página HTML ou figura) de cada vez; não pode gerar tudo de uma vez e mandar tudo pela mesma conexão.
Muitas vezes o que se faz é o JSP gerar o HTML com os links < img > apontando para arquivos gerados por esse JSP em uma outra parte do web site, e que devem ser periodicamente expurgados depois de ficarem por algum tempo à disposição do usuário.
Outras vezes, a página JSP gera um html com um link < img > que aponta para um servlet, o qual só gera a tal da "miniatura"; nesse caso, você precisa alterar sua classe (que será usada pela servlet) para enviar os dados pela OutputStream da servlet.
nao cara … a minha aplicação e desktop mesmo…
Se sua aplicação é Desktop, então como é que você está mostrando as figuras? Você tem um Canvas ou um JPanel onde tem de desenhar suas figuras, ou um JLabel que precisa ter uma figura criada a partir de um java.awt.Image?
eu seleciono a imagem num filechooser , exibo ela dentro de um label atraves de um icon…
mas nao essa a questao… depois que eu seleciono a imagem e exibo ela num label… eu clico num botao enviar q envia a imagem selecionada para um diretorio especifico… mas quando eu subo a img… eu gero duas miniaturas de tamanhos diferentes… e mando as tres.
mas eu tava querendo mandar a imagem redimensioanda…
acho q to conseguindo…
to com o ultimo problema no parametro de localizacao da escrita da imagem…
ex:
writer.write(null, new IIOImage((BufferedImage)listafile.get(3),null,null), iwparam);
onde iwparam e o local onde a imagem será escrita… porem nao to sabendo como setar esse iwparam… com uma string do diretorio q quero