ash
ash

Reputation: 1

Resize JLabel to fit JInternalFrame with an image in it

How to resize an image with JLabel resizing in an internal frame?

I tried some code that I found on the Internet like:

public static BufferedImage resize(Image image, int width, int height) {
    BufferedImage bi = new BufferedImage(width, height, BufferedImage.TRANSLUCENT);
    Graphics2D g2d = (Graphics2D) bi.createGraphics();
    g2d.addRenderingHints(new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY));
    g2d.drawImage(image, 0, 0, width, height, null);
    g2d.dispose();
    return bi;  

or

getScaledInstance(l.getWidth(),  -1, Image.SCALE_SMOOTH);

the code's result

But it only makes the image smaller.

Is there a way to resize the image with the JLabel and JInternalFrame? Any help is welcome :)

Upvotes: 0

Views: 240

Answers (1)

MadProgrammer
MadProgrammer

Reputation: 347184

Scaling an image, well, is not simple. Take a look at:

Scaling can also be expensive, so you'd probably want someway to reduce the number of attempts (as a window been re-resized will be bombarded with a large number of sizing events).

The overall method is the same regardless if your using a JFrame, JPanel or JInternalFrame.

You need some way to monitor for the size changes and some way to determine when it might be a suitable time to scale the image. The following example make use of a ComponentListener and non-repeating Swing Timer. This allows us the ability to schedule a task to be executed in the future, but which can be cancelled if we need to.

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Transparency;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;

public class Main {

    public static void main(String[] args) {
        new Main();
    }

    public Main() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    BufferedImage image = ImageIO.read(getClass().getResource("/images/happy.png"));

                    JInternalFrame internalFrame = new JInternalFrame("Test", true, true, true, true);
                    internalFrame.add(new ImagePane(image));
                    internalFrame.pack();
                    internalFrame.setVisible(true);

                    JDesktopPane desktopPane = new JDesktopPane();
                    desktopPane.add(internalFrame);

                    JFrame frame = new JFrame();
                    frame.add(desktopPane);
                    frame.setSize(new Dimension(800, 800));
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                } catch (IOException ex) {
                    Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        });
    }

    public class ImagePane extends JPanel {

        private Timer resizeTimer;
        private BufferedImage masterImage;
        private JLabel label;
        private Scaler scaler;

        public ImagePane(BufferedImage masterImage) {
            this.masterImage = masterImage;
            label = new JLabel(new ImageIcon(masterImage));

            scaler = new Scaler(masterImage);
            resizeTimer = new Timer(250, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    label.setIcon(new ImageIcon(scaler.getScaledInstanceToFill(getSize())));
                }
            });
            resizeTimer.setRepeats(false);
            addComponentListener(new ComponentAdapter() {
                @Override
                public void componentResized(ComponentEvent e) {
                    resizeTimer.restart();
                }
            });
            setLayout(new BorderLayout());
            add(label);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

    }

    public class Scaler {

        private BufferedImage master;
        private Dimension masterSize;

        private Map<RenderingHints.Key, Object> renderingHints = new HashMap<>();

        public Scaler(BufferedImage master) {
            this.master = master;
            masterSize = new Dimension(master.getWidth(), master.getHeight());
            renderingHints.put(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
            renderingHints.put(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
            renderingHints.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            renderingHints.put(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
            renderingHints.put(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
            renderingHints.put(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
            renderingHints.put(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
            renderingHints.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
            renderingHints.put(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
        }

        public BufferedImage getScaledInstanceToFit(Dimension size) {
            return getScaledInstance(getScaleFactorToFit(size));
        }

        public BufferedImage getScaledInstanceToFill(Dimension size) {
            return getScaledInstance(getScaleFactorToFill(size));
        }

        protected double getScaleFactor(int masterSize, int targetSize) {
            return (double) targetSize / (double) masterSize;
        }

        protected double getScaleFactorToFit(Dimension toFit) {
            double dScaleWidth = getScaleFactor(masterSize.width, toFit.width);
            double dScaleHeight = getScaleFactor(masterSize.height, toFit.height);
            return Math.min(dScaleHeight, dScaleWidth);
        }

        protected double getScaleFactorToFill(Dimension targetSize) {
            double dScaleWidth = getScaleFactor(masterSize.width, targetSize.width);
            double dScaleHeight = getScaleFactor(masterSize.height, targetSize.height);
            return Math.max(dScaleHeight, dScaleWidth);
        }

        protected BufferedImage getScaledInstance(double dScaleFactor) {
            BufferedImage imgScale = master;
            int targetWidth = (int) Math.round(masterSize.getWidth() * dScaleFactor);
            int targetHeight = (int) Math.round(masterSize.getHeight() * dScaleFactor);

            if (dScaleFactor <= 1.0d) {
                imgScale = getScaledDownInstance(targetWidth, targetHeight);
            } else {
                imgScale = getScaledUpInstance(targetWidth, targetHeight);
            }

            return imgScale;
        }

        protected BufferedImage getScaledDownInstance(
                int targetWidth,
                int targetHeight) {

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

            BufferedImage scaled = master;

            if (targetHeight > 0 || targetWidth > 0) {
                int width = master.getWidth();
                int height = master.getHeight();

                do {
                    if (width > targetWidth) {
                        width /= 2;
                        if (width < targetWidth) {
                            width = targetWidth;
                        }
                    }
                    if (height > targetHeight) {
                        height /= 2;
                        if (height < targetHeight) {
                            height = targetHeight;
                        }
                    }

                    BufferedImage tmp = new BufferedImage(Math.max(width, 1), Math.max(height, 1), type);
                    Graphics2D g2 = tmp.createGraphics();
                    g2.setRenderingHints(renderingHints);
                    g2.drawImage(scaled, 0, 0, width, height, null);
                    g2.dispose();

                    scaled = tmp;
                } while (width != targetWidth || height != targetHeight);
            } else {
                scaled = new BufferedImage(1, 1, type);
            }

            return scaled;
        }

        protected BufferedImage getScaledUpInstance(
                int targetWidth,
                int targetHeight) {

            int type = BufferedImage.TYPE_INT_ARGB;

            BufferedImage ret = (BufferedImage) master;
            int width = master.getWidth();
            int height = master.getHeight();

            do {
                if (width < targetWidth) {
                    width *= 2;
                    if (width > targetWidth) {
                        width = targetWidth;
                    }
                }

                if (height < targetHeight) {
                    height *= 2;
                    if (height > targetHeight) {
                        height = targetHeight;
                    }
                }

                BufferedImage tmp = new BufferedImage(width, height, type);
                Graphics2D g2 = tmp.createGraphics();
                g2.setRenderingHints(renderingHints);
                g2.drawImage(ret, 0, 0, width, height, null);
                g2.dispose();

                ret = tmp;
            } while (width != targetWidth || height != targetHeight);
            return ret;
        }
    }
}

Also, JLabel is actually irrelevant to your problem and I'd probably use a custom painting workflow to render the scaled image, but that's me.

Upvotes: 2

Related Questions