Resize image in java

1

I have the following problem. I have an application that takes an image and loads it into a buffer and then I have to resize it. However, using the getScaledInstance() method the image loses a lot of quality.

Below the portion that loaded the image and resizes it:

try {
    BufferedImage imagem = ImageIO.read(new File(
            "D:\Temp\Printer\recibo2.jpg"));     
    Image imagemMenor = imagem.getScaledInstance(600, 835, page);
    g2d.drawImage(imagemMenor, 0, 0, null);
} catch (IOException e) {
    e.printStackTrace();
}

Please let me know the ways to get around this problem.

    
asked by anonymous 16.12.2014 / 20:04

1 answer

3

I've done a brief search of how to resize images in Java , and found that there is more than one way, and this usually means a trade-off between performance and quality .

In your case, the definition of an algorithm ( hint ) to render the image seems to be missing. Not setting it means opting for the default algorithm , and that in turn means speed .

The immediate solution would be to just change the algorithm:

Image imagemMenor = imagem.getScaledInstance(600, 835, Image.SCALE_SMOOTH);

And it's one of the most attractive solutions, if you're talking about quality. But it's also one of the slower .

One tip I've found in many places is to not use getScaledInstace() , only drawImage() , reducing the image up to half its original size , and repeating the process if necessary.

  

Surprisingly, this loop process of reducing the image several times, is up to ten times faster than the others!

I've put some ways to resize an image in the same program for testing purposes. Next to each selection, is the time it took to process the image:

Thedifferencebetweenthreeoptions("Smooth", "Multiples" and "Default"):

Unchangedcodeforresizingimagesusingmultiplesteps,alongwithagoodexplanationofhowclassesworks,isatthislink:The Perils of Image.getScaledInstance ()

Below is my test code:

import java.awt.image.BufferedImage;
import java.awt.*;
import javax.swing.*;
import javax.imageio.ImageIO;
import java.io.*;
import java.net.*;
import java.awt.event.*;
import java.text.DecimalFormat;

public class RedimensionarImagem extends JPanel implements ActionListener {

    BufferedImage img, img1, img2, img3, img4, img5;
    JRadioButton radio1, radio2, radio3, radio4, radio5;
    JPanel painelRadio, painel2;
    JLabel minhaImagem;
    long tempInicial1, tempInicial2, tempInicial3, tempInicial4;
    long tempFinal1, tempFinal2, tempFinal3, tempFinal4;

    public RedimensionarImagem() {

        super(new BorderLayout());


        try {
            // URL url = new URL("http://i.imgur.com/uVKJljD.jpg");
            // URL url = new URL("http://i.imgur.com/Y4ReYrD.jpg");
            URL url = new URL("http://i.imgur.com/kGbo3Ox.jpg");
            img = ImageIO.read(url);

        } catch (IOException e) {
        }

        int imgLargura = img.getWidth();
        int imgAltura = img.getHeight();

        int porcentagem = 25;
        int pTamanho = 100 / porcentagem;

        tempInicial2 = System.nanoTime();
        img2 = usandoDraw1Passo(img, imgLargura/pTamanho,
                                imgAltura/pTamanho);
        tempFinal2 = System.nanoTime();

        tempInicial3 = System.nanoTime();
        img3 = usandoDrawVarios(img, imgLargura/pTamanho,
                                imgAltura/pTamanho);
        tempFinal3 = System.nanoTime();

        tempInicial1 = System.nanoTime();
        img1 = usandoGetScaled(img, imgLargura/pTamanho,
                               imgAltura/pTamanho, Image.SCALE_DEFAULT);
        tempFinal1 = System.nanoTime();

        tempInicial4 = System.nanoTime();
        img4 = usandoGetScaled(img, imgLargura/pTamanho,
                               imgAltura/pTamanho, Image.SCALE_SMOOTH);
        tempFinal4 = System.nanoTime();

        painelRadio = new JPanel();
        painel2 = new JPanel();

        DecimalFormat df = new DecimalFormat("####0.00");

        double segundos1 = (double)(tempFinal1 - tempInicial1) / 1000000000.0;
        double segundos2 = (double)(tempFinal2 - tempInicial2) / 1000000000.0;
        double segundos3 = (double)(tempFinal3 - tempInicial3) / 1000000000.0;
        double segundos4 = (double)(tempFinal4 - tempInicial4) / 1000000000.0;


        radio2 = new JRadioButton("Red. Bilinear de 1 Passo (" +
                                  df.format(segundos2) + "s)");
        radio3 = new JRadioButton("Red. Bil. Multiplos Passos (" +
                                  df.format(segundos3) + "s)");
        radio1 = new JRadioButton("Reducao \"Padrao\" (" +
                                  df.format(segundos1) + "s)");
        radio4 = new JRadioButton("Reducao \"Padrao Smooth\" (" +
                                  df.format(segundos4) + "s)");

        ButtonGroup grupo = new ButtonGroup();

        grupo.add(radio1);
        grupo.add(radio2);
        grupo.add(radio3);
        grupo.add(radio4);

        radio1.addActionListener(this);
        radio2.addActionListener(this);
        radio3.addActionListener(this);
        radio4.addActionListener(this);

        painel2.setLayout(new GridLayout(0,1));

        painelRadio.setLayout(new GridLayout(0,1));
        painelRadio.setBorder(BorderFactory.createEmptyBorder(20,20,20,20));        

        painelRadio.add(radio1);
        painelRadio.add(radio2);
        painelRadio.add(radio3);
        painelRadio.add(radio4);

        minhaImagem = new JLabel();
        minhaImagem.setIcon(new ImageIcon(img3));
        painel2.add(minhaImagem);

        add(painelRadio, BorderLayout.PAGE_END);
        add(painel2, BorderLayout.PAGE_START);

    }

    public static void main(String[] args) {

        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                criarInterface();
            }
        });

    }

    public static void criarInterface() {

        JFrame frame = new JFrame("Redimensionar Imagem");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JComponent painelConteudo = new RedimensionarImagem();
        painelConteudo.setOpaque(true);
        frame.setContentPane(painelConteudo);
        frame.setResizable(false);

        frame.pack();
        frame.setVisible(true);

    }

    public void actionPerformed(ActionEvent e) {

        if (radio1.isSelected()) {
         minhaImagem.setIcon(new ImageIcon(img1));
        }
        if (radio2.isSelected()) {
         minhaImagem.setIcon(new ImageIcon(img2));
        }
        if (radio3.isSelected()) {
         minhaImagem.setIcon(new ImageIcon(img3));
        }
        if (radio4.isSelected()) {
         minhaImagem.setIcon(new ImageIcon(img4));
        }
    }

    public BufferedImage usandoGetScaled(BufferedImage img,
                         int larguraFinal, int alturaFinal, int modo) {

    Image tmp = img.getScaledInstance(larguraFinal, alturaFinal, modo);
    int width = tmp.getWidth(null);
    int height = tmp.getHeight(null);

    BufferedImage novaImagem = new BufferedImage(width, height,
                                   BufferedImage.TYPE_INT_RGB);
    Graphics g = novaImagem.createGraphics();
    g.drawImage(tmp, 0, 0, null);
    g.dispose();

    return novaImagem;

    }

    public BufferedImage usandoDraw1Passo(BufferedImage img,
                         int larguraFinal, int alturaFinal) {

        int largura = img.getWidth();
        int altura = img.getHeight();
        BufferedImage tmp = new BufferedImage(largura, altura,
                                BufferedImage.TYPE_INT_RGB);
        Graphics2D g2 = tmp.createGraphics();
        g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                            RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        g2.drawImage(img, 0, 0, larguraFinal, alturaFinal, null);
        g2.dispose();

        return tmp;
    }

    public BufferedImage usandoDrawVarios(BufferedImage img,
                         int larguraFinal, int alturaFinal) {

        BufferedImage ret = (BufferedImage)img;

        int largura, altura;

        largura = img.getWidth();
        altura = img.getHeight();

        do {
            if (largura > larguraFinal) {
                largura /= 2;
                if (largura < larguraFinal) {
                    largura = larguraFinal;
                }
            }

            if (altura > alturaFinal) {
                altura /= 2;
                if (altura < alturaFinal) {
                    altura = alturaFinal;
                }
            }

            BufferedImage tmp = new BufferedImage(largura, altura,
                                    BufferedImage.TYPE_INT_RGB);
            Graphics2D g3 = tmp.createGraphics();
            g3.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                                RenderingHints.VALUE_INTERPOLATION_BILINEAR);
            g3.drawImage(ret, 0, 0, largura, altura, null);
            g3.dispose();

            ret = tmp;
        } while (largura != larguraFinal || altura != alturaFinal);

        return ret;
    }

}

Sources:

25.10.2015 / 12:19