Scale de BufferedImage: qual opcao usar para melhorar resultado?

6 respostas
Paulo_Silveira

Oi pessoal

Estou fazendo uma reducao de imagem. Para voe ter ideia, ela tem cerca de 2000x2000 pixels e estou passando para 500x500, a imagem original
é praticamente preta e branco, possui 130k, e é um PNG.

Estou usando a forma mais comum, atraves das transformacoes:

static BufferedImage scaleTo(BufferedImage image, int width, int height) {
		AffineTransformOp transform = new AffineTransformOp(AffineTransform.getScaleInstance(
				(double) width / image.getWidth(), (double) height
						/ image.getHeight()), AffineTransformOp.TYPE_BICUBIC);
		return transform.filter(image, null);
}

O resultado é pessimo. Nao se pode ler as letras direito. Com qualquer um dos tipos de AffineTransform.

Algumas pessoas dizem pra aplicar um blur antes de fazer o scale. Tentei, mas nao ficou bom tambem.

Curioso que usando o itext e a Image dele, ele tem um metodo scaleTo que fica bem legivel a versao da imagem reduzida, porem nao obtenho um BufferedImage novamente.

6 Respostas

vfpamp

Oi Paulo,

Tentou usar um resampling baseado no Lanczos? http://en.wikipedia.org/wiki/Lanczos_resampling

O Picasa usa ele, deve te dar bons resultados.

Posta aí se ficar bom :slight_smile:

Paulo_Silveira

vfpamp:
Oi Paulo,

Tentou usar um resampling baseado no Lanczos? http://en.wikipedia.org/wiki/Lanczos_resampling

O Picasa usa ele, deve te dar bons resultados.

Posta aí se ficar bom :)

Em ultimo caso tentarie, mas to procurando algo pronto, ate porque nao é possivel que nao tenha algo que fique bom atraves do JAI ou alguma api padrao!

Valeu Pamplona

C

Reduzir direto usando BICUBIC não é legal. Tente reduzir pra 1000x1000 e entao pra 500x500 ou então use SCALE_AREA_AVERAGING, que é bem pior em termos de performance.

Segue o codigo para as duas possibilidades:

/** * Progressive bilinear scaling: for any downscale size, scale * iteratively by halves using BILINEAR filtering until the proper * size is reached. */ private BufferedImage getOptimalScalingImage(BufferedImage inputImage, int startSize, int endSize) { int currentSize = startSize; BufferedImage currentImage = inputImage; int delta = currentSize - endSize; int nextPow2 = currentSize >> 1; while (currentSize > 1) { if (delta <= nextPow2) { if (currentSize != endSize) { BufferedImage tmpImage = new BufferedImage(endSize, endSize, BufferedImage.TYPE_INT_RGB); Graphics g = tmpImage.getGraphics(); ((Graphics2D)g).setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); g.drawImage(currentImage, 0, 0, tmpImage.getWidth(), tmpImage.getHeight(), null); currentImage = tmpImage; } return currentImage; } else { BufferedImage tmpImage = new BufferedImage(currentSize >> 1, currentSize >> 1, BufferedImage.TYPE_INT_RGB); Graphics g = tmpImage.getGraphics(); ((Graphics2D)g).setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); g.drawImage(currentImage, 0, 0, tmpImage.getWidth(), tmpImage.getHeight(), null); currentImage = tmpImage; currentSize = currentImage.getWidth(); delta = currentSize - endSize; nextPow2 = currentSize >> 1; } } return currentImage; }

Image scaledImage = originalImage.getScaledInstance(scaledSize, scaledSize, Image.SCALE_AREA_AVERAGING);

vfpamp

http://today.java.net/pub/a/today/2007/04/03/perils-of-image-getscaledinstance.html
http://schmidt.devlib.org/jiu/index.html

Paulo_Silveira

Oi Vitor e Carlos. Vou tentar todas as abordagens e postar o que resultou melhor!!! Obrigado pelos toques!
Carlos, sabe de onde é esse codigo? o google indica phugushop. Eh bom?

C

Paulo Silveira:
Oi Vitor e Carlos. Vou tentar todas as abordagens e postar o que resultou melhor!!! Obrigado pelos toques!
Carlos, sabe de onde é esse codigo? o google indica phugushop. Eh bom?

http://filthyrichclients.org/

Criado 3 de maio de 2008
Ultima resposta 3 de mai. de 2008
Respostas 6
Participantes 3