2012-08-10 1072 views
2

我正在製作一個程序,將客戶端屏幕發送到服務器並顯示它,但速度非常慢。一幀需要2-3秒,上傳/下載速度不成問題。有什麼我做錯了/我可以改變以加快速度?Java ImageIO非常慢

服務器:

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(); 
     } 
    } 
} 
+0

你嘗試過什麼到目前爲止找出性能瓶頸?你有沒有做任何分析? – cyroxx 2012-08-10 23:47:33

+0

看這裏:http://stackoverflow.com/questions/2293556/looking-for-a-faster-alternative-to-imageio或在這裏:http://stackoverflow.com/questions/7726583/java-imageio-write-佔用達6秒 – paulsm4 2012-08-11 00:01:06

+0

我很確定它是ImageIO,因爲我記得當我檢查哪種圖像格式最好時,其中一些圖像格式最多需要7秒才能寫入磁盤。 – user1007883 2012-08-11 00:02:12

回答

3

如果您發送的圖像作爲png的GZIPStream可能是一個壞主意。由於png已經具有良好的壓縮率,因此您不會獲得顯着的壓縮增益。根據圖像的種類,您還可以考慮使用jpeg來實現更好的壓縮。

不過,也許最重要的是用BufferedOuputStream包裝輸出流:

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

你可以做同樣的輸入流。

+0

PNG實際上使用zip壓縮,並且使用GZIPInput/OutputStream會讓事情變得更慢(並且最有可能增加數據開銷而不是壓縮)。 – haraldK 2013-06-03 14:08:14

2

你的問題自相矛盾。

一方面你問關於通過套接字發送圖像。另一方面,你說「一幀需要2-3秒,上傳/下載速度不是問題。」

我建議您嘗試配置您的應用程序以確定圖像捕獲,圖像轉換,圖像壓縮或套接字I/O中是否存在瓶頸。其中任何一個都是合理的解釋,而猜測不是識別真實的策略。

(如果您已經知道瓶頸在哪裏......請不要混淆問題的範圍,例如,如果您已經在知道問題出現在圖像中如果你不知道知道這個,那麼不要給我們提供潛在的錯誤信息......比如「上傳/下載速度不對一個問題「。)

0

我相信所有給出的答案都不能解決問題。我懷疑,問題是不是的網絡連接,而是ImageIO.read(InputStream)方法。該版本的方法只是非常慢。如果您嘗試從本地驅動器加載它作爲流(而ImageIO.read(文件)執行得很好),也會發生2-3秒。

我解決了這個問題:

ImageIO.setUseCache(false); 

此處瞭解詳情: Byte array to buffered image conversion slow