Imagens com Qualidade Ruim

Pelo menos meu método ta um pouco melhor… xD

ATUALIZADO -

O thingol tinha razão. Instalei o Image Magick e é simplesmente covardia. Na chamada padrão ela já converte numa imagem redimensionada perfeita !
Além de ser super rápido. E posso chamar nos meus servlets. Testei umas 10 classes Java que encontrei na net e nada chegou nem perto do ImageMagick. A unica mais ou menos levava uns 4 a 5 segundos para converter, isso com meus 2gb de memória etc. Ponto fraquíssimo do JAVA.

Agora a briga é convencer o meu Servidor a instalá-lo. Pois entrei em contato e me passaram que não tinha ainda por motivo de segurança. Safe_Mode…

Alguém tem alguma experiência usando o Image Magick que queira compartilhar ?
Agradeço.

Valeu !!!

Up

Estou à dois dias pesquisando como redimensionar a imagem sem perder tanto a qualidade, assim como vocês aqui…
Em uma das minhas pesquisas achei esse post e tentei usar também as propostas de solução postadas aqui… Mas sem sucesso. A qualidade continuava sempre ruim demais e quando chegava perto de melhorar demorava um abisurdo, rs…
Até que numa das minhas “clicadas” em links alheios cheguei à esse artigo: http://today.java.net/pub/a/today/2007/04/03/perils-of-image-getscaledinstance.html
Com meu inglês fraquinho fui tentando interpretar as dicas meio a tantas maneiras de se redimensionar uma imagem usando apenas java. E entendi que se você redimensionar a imagem original para uma outra imagem vazia usando ScaledImage antes de atribuí-la ao seu objeto Graphics2D a qualidade seria bem melhor e o tempo de processamento menor. Botei, então, a cuca pra funcionar e modifiquei apenas duas linhas daquelas que estava fazendo… E não deu outra! Funcionou como uma luva, rs… Ainda um pouco pesado, mas consegui implementar um método que lê uma imagem num diretório local, copia essa imagem para uma pasta do servidor (que é localhost mesmo, rs), armazena ela em memória, através de BufferedImage, redimensiona a imagem de 2848 X 2136 para 300 X 225 pixels, converte qualquer tipo para jpg e grava novamente a imagem redimensionada no diretório do servidor, excluindo a original, em 3 segundos… E olha que só tenho 1 gb de RAM, meu processador só tem um núcleo e estou rodando meu ubuntu por um live usb, instalado no meu pendrive…
Agora, deixando de ladainha, rsrs, aí estão as míseras linhas de código que redimensionam a imagem:

BufferedImage imageBuffer = new BufferedImage(largura, altura, BufferedImage.TYPE_INT_RGB); Graphics2D graphics2D = imageBuffer.createGraphics(); // aqui é o segredo... redimensiona antes de setar o graphics, com o algoritmo de cálculo de média da área em pixels da imagem... Image scaledImage = imagem.getScaledInstance(largura, altura, Image.SCALE_AREA_AVERAGING); graphics2D.drawImage(scaledImage, 0, 0, largura, altura, null); graphics2D.dispose();Prontinho!
Simples, não!?
Pode não ser tão rápido quanto usando ImageMagik, mas é 100% java e não precisa de “gambiarra” nenhuma pra fazer funcionar, rsrsrsrs…
Com certeza você vai querer modificar pra adequar ainda mais às suas necessidades, e melhorando a ideia poste aqui pra gente poder usurfruir também, rs…
Grande abraço!

Funcionou sim aqui tambem. Fiz uns ajustes pra escolher a imagem por caixa de escolha (FileChooser)

btn_Wallpaper.addActionListener(new ActionListener() {

public void actionPerformed(ActionEvent arg0) {

	JFileChooser chooser = new JFileChooser();

	if (returnVal == JFileChooser.APPROVE_OPTION) {


		mainGUI.app.Change_Back = chooser.getSelectedFile().getAbsolutePath();
		
		
		BufferedImage fundo = null;
		
		try {
			fundo = ImageIO.read(new File(mainGUI.app.Change_Back));
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
			
			JOptionPane.showConfirmDialog(null, "Image fail !");
		}
		
		BufferedImage img_stretched = BufferedImage(fundo, 200, 200);

		ImageIcon icon = new ImageIcon(img_stretched);

                    // Seta a imagem no Jframe mainGUI
		mainGUI.app.lbl_fundo_imagem.setIcon(icon);
}

}

);

[quote=Marky.Vasconcelos]Pra voces.

	public static BufferedImage resize(BufferedImage img, int targetWidth,
			int targetHeight) {
		int type = (img.getTransparency() == Transparency.OPAQUE) ? BufferedImage.TYPE_INT_RGB
				: BufferedImage.TYPE_INT_ARGB;
		BufferedImage ret = (BufferedImage) img;
		int w, h;
		w = img.getWidth();
		h = img.getHeight();

		do {
			if (w > targetWidth) {
				w /= 2;
				if (w < targetWidth) {
					w = targetWidth;
				}
			}
			if (h > targetHeight) {
				h /= 2;
				if (h < targetHeight) {
					h = targetHeight;
				}
			}

			BufferedImage tmp = new BufferedImage(w, h, type);
			Graphics2D g2 = tmp.createGraphics();
			g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
					RenderingHints.VALUE_INTERPOLATION_BICUBIC);
			g2.drawImage(ret, 0, 0, w, h, null);
			g2.dispose();

			ret = tmp;
		} while (w != targetWidth || h != targetHeight);

		return ret;
	}

O problema é que é mais demorado… levou 8,5 segundos pra diminuir uma imagem de 2384x3000 para 400x500. Mas a qualidade ficou excelente.[/quote]

Este código não calcula o aspectRation, mas foi o melhor código para redimensionamento que encontrei, fiz uma alteração para calcular o aspectRation, segue

public static byte[] redimensionarImagem(InputStream imagem, int maxWidth,
			int maxHeigth) throws Exception {

		BufferedImage img = ImageIO.read(imagem);

		int imageWidth = img.getWidth();
		int imageHeight = img.getHeight();

		Dimension largestDimension = new Dimension(maxWidth, maxHeigth);

		float aspectRation = (float) imageWidth / imageHeight;

		if (imageWidth > maxWidth || imageHeight > maxHeigth) {

			if ((float) largestDimension.width / largestDimension.height > aspectRation) {
				largestDimension.width = (int) Math
						.ceil(largestDimension.height * aspectRation);
			} else {
				largestDimension.height = (int) Math
						.ceil((float) largestDimension.width / aspectRation);
			}

			maxWidth = largestDimension.width;
			maxHeigth = largestDimension.height;
		}

		return redimensionar(img, maxWidth, maxHeigth);
	}

	private static byte[] redimensionar(BufferedImage img, int targetWidth,
			int targetHeight) throws Exception {

		int type = (img.getTransparency() == Transparency.OPAQUE) ? BufferedImage.TYPE_INT_RGB
				: BufferedImage.TYPE_INT_ARGB;

		BufferedImage ret = (BufferedImage) img;
		int w, h;
		w = img.getWidth();
		h = img.getHeight();

		do {
			if (w > targetWidth) {
				w /= 2;
				if (w < targetWidth) {
					w = targetWidth;
				}
			}
			if (h > targetHeight) {
				h /= 2;
				if (h < targetHeight) {
					h = targetHeight;
				}
			}

			BufferedImage tmp = new BufferedImage(w, h, type);
			Graphics2D g2 = tmp.createGraphics();
			g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
					RenderingHints.VALUE_INTERPOLATION_BICUBIC);
			g2.drawImage(ret, 0, 0, w, h, null);
			g2.dispose();

			ret = tmp;
		} while (w != targetWidth || h != targetHeight);

		return bufferedImageToByteArray(ret);
	}

Aproveitando o tópico ressuscitado, essa API faz o escalonamento. É de altíssima qualidade, fácil de usar e extremamente rápida:
http://code.google.com/p/java-image-scaling/

Raiduster, ao ressuscitar tópicos, deixe claro que você está ressuscitando e porque. Não responda casualmente a um usuário que postou em 2009, como se ele tivesse feito isso ontem.

Finalmente, o termo correto é aspect ratio, não aspect ratio[color=red]n[/color].