Imagens com Qualidade Ruim

Galera, to com um problema que não sei mais o que fazer. Tenho um gerenciador de galeria de fotos. Tô usando um método para redimensionar as fotos e adicionar uma marca dágua, só que ele tem dois problemas: QUALIDADE RUIM DOS THUMBS E CONSOME MUITA MEMÓRIA.
O mais sério é a QUALIDADE, que meus clientes reclamam demais. Alguém tem um método show de bola ai não ?

Segue os métodos:

[code]public static void gerarThumbnail(InputStream inputStream, OutputStream out, int thumbAltura, int thumbLargura, float quality) throws Exception{

        Image image = null;
        int largura = 0;
        int altura = 0;


        try {
        //Recuperar os valores de LARGURA/ALTURA e ALTERAR no registro da FOTO
        image = ImageIO.read(inputStream);
        largura = image.getWidth(null);
        altura = image.getHeight(null);
        
        
        
        } catch (Exception e) {
        throw new Exception("ERRO ALTERANDO TAMANHO DA IMAGEM " + e);
        }

        try {

        //Fazer a geracao do TumbNail levando em conta o tamanho da ALTURA
        MediaTracker mediaTracker = new MediaTracker(new Container());
        mediaTracker.addImage(image, 0);
        mediaTracker.waitForID(0);

        // determine thumbnail size from WIDTH and HEIGHT
        double thumbPorcentagem;
        
        if(thumbLargura == 0){
            thumbPorcentagem = ((thumbAltura*100.0)/altura)/100.0;

            if(thumbLargura == 0){
            thumbLargura = (int)(largura * thumbPorcentagem);
            }
        }

        if(thumbAltura == 0){
            thumbPorcentagem = ((thumbLargura*100.0)/largura)/100.0;

            if(thumbAltura == 0){
            thumbAltura = (int)(altura * thumbPorcentagem);
            }
        }            
        
        // draw original image to thumbnail image object and
        // scale it to the new size on-the-fly
        BufferedImage thumbImage = new BufferedImage(thumbLargura,thumbAltura, BufferedImage.TYPE_INT_RGB);
        Graphics2D graphics2D = thumbImage.createGraphics();
        graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BILINEAR); //VALUE_INTERPOLATION_BICUBIC - For speed better use RenderingHints.VALUE_INTERPOLATION_BILINEAR
        
        graphics2D.drawImage(image, 0, 0, thumbLargura, thumbAltura, null);
        graphics2D.dispose();
        
        // save thumbnail image to OUTFILE
        JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
        JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(thumbImage);

        param.setQuality(quality, false); //The quality argument from the command line is converted from the interval 0 to 100 to the interval 0.0f to 1.0f, because that's what the codec expects (I mostly use 0.75f).
        encoder.setJPEGEncodeParam(param);
        encoder.encode(thumbImage);
        
        /* ALTERAÇÕES EM  26/12/2008 */
        graphics2D.dispose();
        image.flush();
        thumbImage.flush();
        /* ------------------------------------ */
        
        inputStream.close();
        out.flush();
        out.close();
        

        } catch (Exception e) {
        throw new Exception("ERRO SALVANDO O THUMBNAIL DA IMAGEM " + e);
        }
        }

        public static void gerarWatermark(InputStream imagemOriginal, InputStream imagemWatermark, OutputStream imagemGerada,String posicao,float alpha){

        try {

        BufferedImage im = ImageIO.read(imagemOriginal);
        BufferedImage im2 = ImageIO.read(imagemWatermark);
        Graphics2D g = im.createGraphics();            
        g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha));
        
        
        //g.drawImage(im2, (im.getWidth()-im2.getWidth())/2, (im.getHeight()-im2.getHeight())/2, null);
        
                   
        // TOP ESQUERDO 
        if(posicao.equals("7")){
        g.drawImage(im2, 0, 0, null); 
                    
        // TOP CENTRO
        }else if(posicao.equals("8")){
        g.drawImage(im2, (im.getWidth()-im2.getWidth())/2, 0, null); 
                    
        // TOP DIREITO
        }else if(posicao.equals("9")){
        g.drawImage(im2, (im.getWidth()-im2.getWidth()), 0, null); 
                    
        // CENTRO ESQUERDO
        }else if(posicao.equals("4")){
        g.drawImage(im2, 0, (im.getHeight()-im2.getHeight())/2, null);

        // CENTRO
        }else if(posicao.equals("5")){
        g.drawImage(im2, (im.getWidth()-im2.getWidth())/2, (im.getHeight()-im2.getHeight())/2, null);
        
        // CENTRO DIREITO
        }else if(posicao.equals("6")){
        g.drawImage(im2, (im.getWidth()-im2.getWidth()), (im.getHeight()-im2.getHeight())/2, null);
        
        // BASE ESQUERDA
        }else if(posicao.equals("1")){
        g.drawImage(im2, 0, (im.getHeight()-im2.getHeight()), null);

        // BASE CENTRO
        }else if(posicao.equals("2")){
        g.drawImage(im2, (im.getWidth()-im2.getWidth())/2, (im.getHeight()-im2.getHeight()), null);
        
        // BASE DIREITA
        }else if(posicao.equals("3")){
        g.drawImage(im2, (im.getWidth()-im2.getWidth()), (im.getHeight()-im2.getHeight()), null);
        }
        
        g.dispose();
        ImageIO.write(im, "jpeg", imagemGerada);
        
        /* ALTERAÇÕES EM  26/12/2008 */
        im.flush();
        im2.flush();
        /* --------------------------- */
        
        imagemOriginal.close();
        imagemWatermark.close();
        imagemGerada.flush();
        imagemGerada.close();
        
        

        } catch (Exception e) {
        System.out.println(e);
        }

}

public static void gerarWatermark(InputStream imagemOriginal, String textoWatermark, OutputStream imagemGerada){

try {

BufferedImage im = ImageIO.read(imagemOriginal);

//Preparando o Graphics 2D para incluir o texto na imagem
Graphics2D g = im.createGraphics();
g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

//Setar a font utilizada no texto
g.setFont(new Font(“Lucida Bright”, Font.ITALIC, 60));

//Efeitos de rotacao no texto
g.rotate(-Math.PI/4, im.getWidth()/2, im.getHeight()/2);

//Setando o valor do texto
TextLayout tl = new TextLayout(textoWatermark, g.getFont(), g.getFontRenderContext());

//???
Rectangle2D bounds = tl.getBounds();
double x = (im.getWidth()-bounds.getWidth())/2 - bounds.getX();
double y = (im.getHeight()-bounds.getHeight())/2 - bounds.getY();

//
Shape outline = tl.getOutline(AffineTransform.getTranslateInstance(x+2, y+1));

// Montando a saida
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1.0f)); // Estava 0.3
g.setPaint(Color.WHITE);
g.draw(outline);
g.setPaint(new GradientPaint(0, 0, Color.WHITE, 30, 20, new Color(128,128,255), true));
tl.draw(g, (float)x, (float)y);
g.dispose();

ImageIO.write(im, “jpeg”, imagemGerada);
imagemOriginal.close();
imagemGerada.close();
imagemGerada.flush();
imagemGerada.close();

} catch (Exception e) {
System.out.println(e);
}
}[/code]

Aê galera, me acuda ai.

Ninguem conhece ?..to começando a ficar preocupado…

Sabe o que é cara… não é maldade não… é que seu código está macarrão… aí fica difícil achar alguma coisa…

OO aí graças a API do Java… senão…

Cara, não sou expert em JAva, longe disso…mas todas as linhas deste codigo eu entendi a teoria. Além de que estar comentado.
Obs.: Peguei num site gringo especializado.
Tem certeza que vc chegou a lê-lo ? …rsrs

E pelo que entendi a “dificuldade” ai não esta na macarronada, e sim na metodologia usada. Creio que existe bibliotecas mais úteis e eficazes
para fazer isso. Apesar de já ter pesquisado e visto muita coisa, quase tudo a mesma coisa. Por isso estou perguntando para alguém ( que existe com certeza ) que já precisou destes métodos para trabalhos semelhantes.

eu entendi… hehehehehehe… não esquenta véio… todo mundo começa assim. Não lí pq não poderei ajudá-lo tendo em vista que não manjo nada de trabalho de imagens… sacou ?? O que quis dizer foi o seguinte:

Você perguntou isso e eu respondi que não é bem isso… realmente é complicado… se tira alguns minutinhos entre uma tarefa e outra pra tentar ajudar… ler tudo aquilo de código, demanda um tempo, que a maioria que pode lhe ajudar, que complica… entendeu ??

Mas é isso aí… uma hora seu salvador aparece por aqui… ou então tenta sintetizar nos pontos críticos… pode ajudar tbm…

Falows :wink:

Pra não sair do seco da conversa… dá uma olhada aí… não sei se te ajuda…

http://today.java.net/pub/a/today/2007/04/03/perils-of-image-getscaledinstance.html

Dá uma Googlada também:

http://www.google.com.br/search?q=Thumbnail+em+Java&ie=utf-8&oe=utf-8&aq=t&rls=com.ubuntu:pt-BR:unofficial&client=firefox-a

Postei a um tempo em outro tópico.

Se voce adaptar da pra voce usar no seu código.

int wDest = 250;//largura
int hDest = 250;//altura
BufferedImage src = //Sua imagem
BufferedImage dest = new BufferedImage(wDest,hDest,BufferedImage.TYPE_INT_RGB);//250x250 o tamanho da imagem que vai ficar ao final.
Graphics2D g = dest.createGraphics();
AffineTransform at = AffineTransform.getScaleInstance(
(double)wDest/src.getWidth(),
(double)hDest/src.getHeight());
g.drawRenderedImage(src,at);
//dest agora tem 250x250 pixels e com a imagem redimensionada.

A qualidade fica boa ai do thumb deste código ?

Sim.

Nda. Nenhum dessas funções deixa com a qualidade legal. Como falei com o amigo ai de cima, o problema é no controle do sharp, da nitidez.
Com o java parece q ele dah uma dose exagerada de nitidez, deixando a imagem ruim.
Veja o exemplo do que estou falando:

REDIMENSIONADO DE 3072X2304 para 400X300px

TESTE COM PHOTOSHOP

TESTE COM OS MÉTODOS JAVA ( acima )

Quem souber o que controla a nitidez ai resolve um dos problemas.

Tenta rodar esse código
http://www.furutani.com.br/site/MostrarArtigo.action?codigo=9
as vezes ajuda

Peguei este método ai:

[code] public static void redimensionar(Image image, int width, int height, int quality,
String nomeImagem) {

	// Calculos necess�rios para manter as propo�oes da imagem, conhecido
	// como "aspect ratio"
	double thumbRatio = (double) width / (double) height;
	int imageWidth = image.getWidth(null);
	int imageHeight = image.getHeight(null);

	double imageRatio = (double) imageWidth / (double) imageHeight;

	if (thumbRatio < imageRatio) {
		height = (int) (width / imageRatio);
	} else {
		width = (int) (height * imageRatio);
	}
	// Fim do c�lculo

	BufferedImage thumbImage = new BufferedImage(width, height,
			BufferedImage.TYPE_INT_RGB);

	Graphics2D graphics2D = thumbImage.createGraphics();

	graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
			RenderingHints.VALUE_INTERPOLATION_BILINEAR);

	graphics2D.drawImage(image, 0, 0, width, height, null);

	BufferedOutputStream out;

	try {

                String imagesDir = "D:/";

		out = new BufferedOutputStream(new FileOutputStream(imagesDir
				+ nomeImagem));
		JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
		JPEGEncodeParam param = encoder
				.getDefaultJPEGEncodeParam(thumbImage);
		quality = Math.max(0, Math.min(quality, 100));
		param.setQuality((float) quality / 100.0f, false);
		encoder.setJPEGEncodeParam(param);
		encoder.encode(thumbImage);
		out.close();

	} catch (FileNotFoundException e) {
		System.out.println("FileNotFoundException " + e.getMessage());
	} catch (ImageFormatException e) {
		System.out.println("ImageFormatException " + e.getMessage());
	} catch (IOException e) {
		System.out.println("IOException " + e.getMessage());
	}
}

}[/code]

e chamei

[code]

File file = new File(“D:/original.jpg”);
Image imagem = new ImageIcon(file.toURL()).getImage();

            MyImages.redimensionar(imagem, 400, 300, 95, "testeF.jpg");[/code]

Mas não funcionou. A Imagem criada ficou preta, sem nada.
Tentei também com:

BufferedImage imagem = ImageIO.read(new File("D:/original.jpg"));

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.

to chamando o método
BufferedImage imagem = ImageIO.read(new File(“D:/original.jpg”));
MyClass.resize(imagem, 400, 300);

Mas nada acontece… o q tah faltando ?

O método esta completo ?

Faltou atribuir a algum objeto

BufferedImage imagem = ImageIO.read(new File("D:/original.jpg"));
BufferedImage imagemRedimensionada = MyClass.resize(imagem, 400, 300);

Ainda não estamos lá…veja e comparem a qualidade:

PHOTOSHOP

MEUS MÉTODOS ATUAIS JAVA

O METODO DO AMIGO AÍ

SCORE: 2 x 0 pro Photoshop.

AÊ galera, vamo matar essa !!!

Laelson, que tal tentar experimentar o ImageMagick?

Embora seja em C, você pode invocá-lo por uma linha de comando (ou seja, via JImageMagick: http://www.imagemagick.org/script/api.php#java )
Talvez haja algum conjunto de parâmetros que crie uma imagem tão boa quanto a do Photoshop. Basta você experimentar um pouco com os parâmetros. É bem capaz de além disso acabar sendo mais rápido que o Java, já que pode usar todos os núcleos do processador caso desejado.

http://www.imagemagick.org/Usage/resize/
http://www.imagemagick.org/Usage/misc/#interpolate

Não entendo nada de C. Tipo, tenho meu sistema/sites hospedados num servidor com Tomcat e etc… Seria possível eu rodar o C no servidor ou vou ter que pedir pra instalar C, módulos e tals e tals… ?