【问题标题】:Java ImageIO is insanely slowJava ImageIO 非常慢
【发布时间】:2012-08-10 23:45:45
【问题描述】:

我正在制作一个程序,将客户端屏幕发送到服务器并显示它,但它非常慢。一帧需要2-3秒,上传/下载速度不是问题。有什么我做错了/我可以改变什么来加快速度吗?

服务器:

import java.awt.BorderLayout;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.zip.GZIPInputStream;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

public class Server {

    public static void main(String[] args) {
        try {
            JPanel panel = new JPanel();
            panel.setLayout(new BorderLayout());

            JLabel label = new JLabel();
            label.setSize(800, 600);
            label.setVisible(true);

            JScrollPane scroll = new JScrollPane();
            scroll.getViewport().add(label);
            panel.add(scroll, BorderLayout.CENTER);

            JFrame frame = new JFrame();
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.getContentPane().add(panel);
            frame.setSize(800, 600);
            frame.setVisible(true);

            ServerSocket serverSocket = new ServerSocket(25565);
            Socket socket = serverSocket.accept();
            GZIPInputStream in = new GZIPInputStream(socket.getInputStream());
            BufferedImage image = null;
            while(socket.isConnected()) {
                image = ImageIO.read(in);
                if(image != null) {
                    label.setIcon(new ImageIcon(image));
                    label.repaint();

                }
            }
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

客户:

import java.awt.AWTException;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.io.IOException;
import java.net.Socket;
import java.util.zip.GZIPOutputStream;

import javax.imageio.ImageIO;

public class Client {

    public static void main(String[] args) {
        try {
            Robot robot = new Robot();
            Toolkit toolkit = Toolkit.getDefaultToolkit();
            Rectangle screen = new Rectangle((int) toolkit.getScreenSize().getWidth(), (int) toolkit.getScreenSize().getHeight());
            Socket socket = new Socket("127.0.0.1", 25565);
            GZIPOutputStream out = new GZIPOutputStream(socket.getOutputStream());

            while(socket.isConnected()) {
                ImageIO.write(robot.createScreenCapture(screen), "png", out);
            }
            out.close();
        } catch (AWTException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

【问题讨论】:

  • 到目前为止,您尝试了哪些方法来确定性能瓶颈?你做过分析吗?
  • 我很确定它是 ImageIO,因为我记得当我检查哪种图像格式最好时,其中一些只需要 7 秒才能写入磁盘。
  • @paulsm4 我真的不想使用任何库,但如果我找不到其他选择,我会的。还有其他想法吗?
  • 您应该首先在分析器下运行程序以查看时间的去向。当知道如此容易时,猜测是愚蠢的。我非常喜欢 Netbeans 分析器界面。

标签: java image screenshot javax.imageio


【解决方案1】:

我相信所有给出的答案都不能解决问题。我怀疑问题出在不是网络连接,而是 ImageIO.read(InputStream) 方法。这个版本的方法简直太慢了。如果您尝试从本地驱动器将其作为流加载(而 ImageIO.read(File) 执行得很好),也会发生 2-3 秒。

我解决了这个问题:

ImageIO.setUseCache(false);

更多信息在这里: Byte array to buffered image conversion slow

【讨论】:

    【解决方案2】:

    如果您以png 发送图像,则 GZIPStream 可能是个坏主意。您不会获得显着的压缩增益,因为 png 已经具有良好的压缩效果。根据图像类型,您还可以考虑使用jpeg 以实现更好的压缩。

    但可能最重要的是用 BufferedOuputStream 包装输出流:

    BufferedOutputStream out = new BufferedOutputStream(socket.getOutputStream());
    

    你可以在输入流中做同样的事情。

    【讨论】:

    • PNG 实际上使用 zip 压缩,而使用 GZIPInput/OutputStream 只会让事情变慢(而且很可能会增加数据开销而不是压缩)。
    【解决方案3】:

    你的问题自相矛盾。

    一方面,您询问有关通过套接字发送图像的问题。另一方面,您说“一帧需要 2-3 秒上传/下载速度不是问题。”

    我建议您尝试分析您的应用程序以确定瓶颈是在图像捕获、图像转换、图像压缩还是套接字 I/O。其中任何一种都是似是而非的解释,而猜测不是识别真实解释的好策略。

    (如果您已经知道瓶颈在哪里......不要通过在问题中包含其余步骤来混淆问题。例如,如果您已经知道问题在图像转换中,您甚至无需提及您是通过网络发送图像。但是如果您不知道这一点,请不要向我们提供潜在的虚假信息...比如“上传/下载速度不是问题”。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-10-14
      • 1970-01-01
      • 2012-08-17
      • 2015-12-05
      • 2016-03-26
      • 2015-05-22
      • 1970-01-01
      • 2017-12-12
      相关资源
      最近更新 更多