Resize image in java

Asked

Viewed 3,777 times

1

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

Below the chunk that loads 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();
}

I ask you to show me ways around this problem.

  • You can post an example of the original image and the enlarged image?

1 answer

3

I did a brief research on how to resize images in Java, and found that there is more than one way, and that usually means an exchange between performance and quality.

In your case, the definition of an algorithm seems to be missing (hint) to process the image. Do not set it means opt for the standard algorithm, and this, in turn, means rapidity.

The immediate solution would just be to change the algorithm:

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

And it’s one of the most attractive solutions, if you talk about quality. But it’s also one of the slower.

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

Surprisingly, this process in loop to reduce the image several times, to be ten times faster than the others!

I 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:

Redimensionamento Padrão

The difference between three of the options ("Smooth", "Multiple Steps" and "Standard"):

Amostras de cada processo de imagem

The unchanged code for resizing images using multiple steps, along with a good explanation of how the classes, is at this link: The Perils of Image.getScaledInstance()

Follow below 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:

Browser other questions tagged

You are not signed in. Login or sign up in order to post.