1

我正在尝试缩放由以下人员拍摄的屏幕截图:

robot.createScreenCapture(SCREEN_RECT);

我试图将其缩小为 600X400 的图像并适合 600X400 的 JFrame 我的程序正在使用摇摆工人从每张图片或帧中创建视频。每个帧有 200 毫秒的延迟。当被告知重新缩放时,图像仅以原始尺寸显示原始图像。有谁知道如何解决这个问题,还是我应该放弃调整大小?

@SuppressWarnings("serial")
public class temporaryShit extends JPanel 
{
    private static final int width = 600;
    private static final int height = 400;
    private JLabel displayedLabel = new JLabel();

    public temporaryShit() 
    {
        setLayout(new BorderLayout());
        add(displayedLabel);
        try {
            MySwingWorker mySwingWorker = new MySwingWorker();
            mySwingWorker.execute();
        } catch (AWTException e) {
        }
    }

    public void setLabelIcon(Icon icon) {
        displayedLabel.setIcon(icon);
    }

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

    private class MySwingWorker extends SwingWorker<Void, Icon> 
    {
        private final Rectangle SCREEN_RECT = new Rectangle(0, 0, width, height);
        private long delay = 200;
        private Robot robot = null;

        public MySwingWorker() throws AWTException 
        {
            robot = new Robot();
        }

        @Override
        protected Void doInBackground() throws Exception 
        {
            Timer utilTimer = new Timer();
            TimerTask task = new TimerTask() 
            {
                @Override
                public void run() 
                {
                    BufferedImage capturedImage = captureScreen();
                    publish(new ImageIcon(capturedImage));
                }
            };
            utilTimer.scheduleAtFixedRate(task, delay, delay);
            return null;
        }

        @Override
        protected void process(List<Icon> chunks) 
        {
            for (Icon icon : chunks) 
            {
                setLabelIcon(icon);
            }
        }

        private BufferedImage captureScreen() 
        {
            BufferedImage img = robot.createScreenCapture(SCREEN_RECT);
            return createResizedImage(img, width, height);
        }

        public BufferedImage createResizedImage(Image original, int width, int height) 
        {
            BufferedImage scaledBI = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
            Graphics2D g = scaledBI.createGraphics();
            g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
            g.drawImage(original, 0, 0, width, height, null);
            g.dispose();
            return scaledBI;
        }
    }

    private static void createAndShowGui() 
    {
        temporaryShit mainPanel = new temporaryShit();

        JFrame frame = new JFrame("SwingWorker Eg");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(mainPanel);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    public static void main(String[] args) 
    {
        SwingUtilities.invokeLater(new Runnable() 
        {
            public void run() 
            {
                createAndShowGui();
            }
        });
    }
}
4

2 回答 2

2

您已经有了一个指定大小的新图像 - scaled,可用于渲染。

这是一个简单的例子:

在此处输入图像描述

import java.awt.Image;
import java.awt.image.BufferedImage;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;

class TestBrightness {
    public static void main(String args[]) {
        try {
            URL imageUrl = new URL(
                    "http://duke.kenai.com/comfyChair/ComfyChairRadSmall.jpg");

            BufferedImage ioImage = ImageIO.read(imageUrl);

            JPanel panel = new JPanel();
            Image scaledImg = ioImage.getScaledInstance(ioImage.getWidth() / 2, 
                    ioImage.getHeight() / 2, Image.SCALE_SMOOTH);

            panel.add(new JLabel(new ImageIcon(ioImage)));
            panel.add(new JLabel(new ImageIcon(scaledImg)));

            JOptionPane.showMessageDialog(null, panel, "100% vs 50%",
                    JOptionPane.INFORMATION_MESSAGE);

        } catch (Exception e) {
            JOptionPane.showMessageDialog(null, e.getMessage(), "Failure",
                    JOptionPane.ERROR_MESSAGE);
            e.printStackTrace();
        }
    }
}

作为旁注,有很多方法可以缩放图像,Image.getScaledInstance()可能不是最好的。您可能有兴趣查看Image.getScaledInstance() 的风险,了解有关Image.getScaledInstance()

编辑:问题更新

最后一个问题更新删除了有关此答案的所有详细信息getScaledInstance并使该答案无效。getScaledInstance是一个非常慢的方法,它也是异步的。试试这个方法来获得一个调整大小的图像:

public static BufferedImage createResizedImage(Image original, int width,
        int height) {
    BufferedImage scaledBI = new BufferedImage(width, height,
            BufferedImage.TYPE_INT_ARGB);
    Graphics2D g = scaledBI.createGraphics();
    g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
            RenderingHints.VALUE_INTERPOLATION_BILINEAR);
    g.drawImage(original, 0, 0, width, height, null);
    g.dispose();
    return scaledBI;
}

您可能想要更改渲染提示以获得更好的质量。

要获得更好、更完整的图像缩放器,请查看Filthy Rich Clients书中 的getFasterScaledInstance()

编辑:最后一个问题更新与发布的代码和 SwingWorker

执行SwingWorker不正确。doInBackground()时间表java.Utils.Timer。此计时器处理所有更新,而实际的SwingWorker工作线程结束。计时器的所有更新都不是在Event Dispatch Thread上触发的。ImageIcon不在 EDT上分配可能不安全。并且可以肯定更新 UI 是不安全的,即setLabelIcon()不在 EDT 上调用。有关详细信息,请参阅Swing 中的并发教程。

您可以添加while循环和删除计时器Thread.sleepdoInBackground()或者,Swing 计时器可能更适合这种情况。这是一个例子:

import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;

public class DemoRobotPanel extends JPanel{
    private static final long serialVersionUID = 1L;

    private Image image;
    private Robot robot;
    private Rectangle CAPTURE_RECT;
    private int TIMER_DELAY = 1000;
    private int desiredWidth = 600;
    private int desiredHeight = 400;

    public DemoRobotPanel() {
        CAPTURE_RECT = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());

        try {
            robot = new Robot();

            ActionListener taskPerformer = new ActionListener() {
                public void actionPerformed(ActionEvent evt) {
                    try {
                        BufferedImage img = robot.createScreenCapture(CAPTURE_RECT);
                        setImage(img);
                    } catch (HeadlessException e) {
                        e.printStackTrace();
                    }
                }
            };

            Timer timer = new Timer(TIMER_DELAY, taskPerformer);
            timer.start();

        } catch (AWTException ex) {
            // TODO Auto-generated catch block
            ex.printStackTrace();
        }
    }

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

    public void setImage(Image image) {
        this.image = image;
        repaint();
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        if (image != null)
            g.drawImage(image, 0, 0, getWidth(), getHeight(), this);
    }

    private static void createAndShowGui()  {
        final DemoRobotPanel panel = new DemoRobotPanel();
        JFrame frame = new JFrame("Demo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(panel);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGui();
            }
        });
    }
}
于 2013-04-20T16:24:18.950 回答
0

尝试这个:


    public BufferedImage resize(BufferedImage bufferedImage, int resizeWidth, int resizeHeight) {
        // Create new (blank) image of required (scaled) size
        BufferedImage scaledImage = new BufferedImage(resizeWidth, resizeHeight, BufferedImage.TYPE_INT_ARGB);
        // Paint scaled version of image to new image
        Graphics2D graphics2D = scaledImage.createGraphics();
        graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        graphics2D.drawImage(bufferedImage, 0, 0, resizeWidth, resizeHeight, null);
        graphics2D.dispose();
        return scaledImage;
    }

您可能想尝试不同的 RenderingHints。

于 2013-04-20T17:27:11.357 回答