Redirecionamento de Imagem perdendo qualidade

8 respostas
J

Boa tarde Amigos,

Estou com um problema no redimensionamento de imagens em relação a qualidade, consigo redimensionar perfeito, porem a qualidade é perdida!

Segue oq estou fazendo:

public static String redimensionar(String fileName, int largura, int altura) throws IOException {
		FileInputStream fis = new FileInputStream(new File(fileName));
    	BufferedImage imagem = ImageIO.read(fis);
    	
    	BufferedImage new_img = new BufferedImage(largura, altura, BufferedImage.TYPE_INT_RGB);
		Graphics2D g = new_img.createGraphics();
		g.drawImage(imagem, 0, 0, largura, altura, null);
		
		String extensao = "jpg";
		String nome = String.valueOf(Calendar.getInstance().getTimeInMillis()) + "." + extensao;
		String newFileName = System.getProperty("java.io.tmpdir") + System.getProperty("file.separator") + nome;
		
		ImageIO.write(new_img, "JPG", new File(newFileName));

		return newFileName;
	}

Se alguem puder me ajudar, agradeço …

8 Respostas

KWill

A perda de qualidade é praticamente inevitável em redimensionamento de imagens, mas daria para passar alguns RenderingHints para tentar reduzir essa perda.
Salvar em formatos “lossless” como “PNG” também pode ajudar.

Inté.

ViniGodoy

A compressão que o Java usa para o .jpg é muito agressiva.
Dê uma olhada nesse artigo, que explica como usar um método de compressão de maior qualidade:

http://www.universalwebservices.net/web-programming-resources/java/adjust-jpeg-image-compression-quality-when-saving-images-in-java

J

Obrigado a todos,

ViniGodoy, vi o artigo, alterei o codigo, porem continua sem qualidade. Aumentou um pouco o tamanho do arquivo só! hehehe

Segue alteração que fiz:
public static String redimensionar(String fileName, int tamanhoMaximo) throws IOException {
    	int largura = 0;
    	int altura = 0;
		FileInputStream fis = new FileInputStream(new File(fileName));
    	BufferedImage imagem = ImageIO.read(fis);
    	
    	/**
    	 * Calcula proporcionalidade de acordo com o tamanhoMaximo
    	 */
    	if (imagem.getWidth() > imagem.getHeight()) {
    		largura = tamanhoMaximo;
    		altura = (int) (largura * imagem.getHeight() / imagem.getWidth());
    	} else {
    		altura = tamanhoMaximo;
    		largura = (int) (altura * imagem.getWidth() / imagem.getHeight());
    	}
    	
    	BufferedImage new_img = new BufferedImage(largura, altura, BufferedImage.TYPE_INT_RGB);
//    	new_img.getGraphics().drawImage(imagem, 0, 0, largura, altura, null);
    	
    	Graphics2D g = new_img.createGraphics();
		g.drawImage(imagem, 0, 0, largura, altura, null);
		
		String tmp[] = fileName.split(".");
		String extensao = "jpg"; //tmp[tmp.length - 1];
		String nome = String.valueOf(Calendar.getInstance().getTimeInMillis()) + "." + extensao;
		String newFileName = System.getProperty("java.io.tmpdir") + System.getProperty("file.separator") + nome;
		
//		ImageIO.write(new_img, "jpg", new File(newFileName));

		Iterator<ImageWriter> iter = ImageIO.getImageWritersByFormatName("jpeg");

		ImageWriter writer = (ImageWriter)iter.next();
		ImageWriteParam iwp = writer.getDefaultWriteParam();
		
		iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
		iwp.setCompressionQuality(1); // an integer between 0 and 1
		// 1 specifies minimum compression and maximum quality
		
		FileImageOutputStream output = new FileImageOutputStream(new File(newFileName));
		writer.setOutput(output);
		IIOImage image = new IIOImage(new_img, null, null);
		writer.write(null, image, iwp);
		writer.dispose();
		
		return newFileName;
	}
Valeu
ViniGodoy

Tente passar alguns renderinghints para o seu Graphics:

g.setRenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g.setRenderingHints(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); g.setRenderingHints(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);

E

Você está aumentando o tamanho da imagem? Se estiver fazendo isso, não é só o problema do JPEG que faz diminuir a qualidade.
Ou seja, você tem de usar a dica do ViniGodoy.

Graphics2D g = new_img.createGraphics();  
         g.setRenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);  
         g.setRenderingHints(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);  
         g.setRenderingHints(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);  
         g.drawImage(imagem, 0, 0, largura, altura, null);
E

Se estiver diminuindo a imagem, pode ler este artigo:

http://www.componenthouse.com/article-20

J

Tb nao foi …

Graphics2D g = new_img.createGraphics();
		g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
		g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
		g.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
		g.drawImage(imagem, 0, 0, largura, altura, null);
J

Valeu pela dica entanglement,

inclui algumas coisas do artigo com o link do ViniGodoy, acho que melhorou um pouco …

Ainda vou fazer uns teste pra ver …

Mas segue codigo alterado:

int type = imagem.getType() == 0 ? imagem.TYPE_INT_ARGB : imagem.getType();
BufferedImage new_img = new BufferedImage(largura, altura, type);
Graphics2D g = new_img.createGraphics();
g.setComposite(AlphaComposite.Src);
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.drawImage(imagem, 0, 0, largura, altura, null);
g.dispose();

Agradeço a todos…
Abraço.

Criado 20 de outubro de 2010
Ultima resposta 20 de out. de 2010
Respostas 8
Participantes 4