2014-01-19 47 views
1

我有BufferedImage显示在JFrame,我想要通过Socket(byte[] buffer)收到的原始R,G,B数据定期刷新。动作序列应该是这样的:定期刷新BufferedImage

  1. 接收字节[1280 * 480]纯的RGB数据(每个部件的一个字节)的阵列 - >该部分通过字节数组工作无瑕疵
  2. 迭代和呼叫BufferedImage.setRgb(x, y, RGB)为每个像素

我没有接收和显示一帧的问题,但是当我执行步骤1和2的代码时,我会定期接收数据,但不会显示单个帧。我的猜测是,接收数据比显示图像要快得多,换句话说,我的接收图像被某种新图像覆盖了。 我的下一个想法是将缓冲区与图像交换到另一个后台线程,并阻止进行网络通信的主线程直到后台线程完成“显示”图像。 然后我听到它可以很容易地用SwingWorker在这里:Can a progress bar be used in a class outside main?完成,但它完全一样的事情,如果我仍然在一个线程上做所有事情:没有图像显示。这里是我的代码:

public class ConnectionManager { 

public static final String serverIp = "192.168.1.10"; 
public static final int tcpPort = 7; 
public static final int bufferSize = 1280; 

private Socket client; 
private BufferedInputStream networkReader; 
private PrintStream printStream; 

byte[] buffer; 

public ConnectionManager(){} 

public void connect() throws IOException{ 
    int dataRead; 
    while(true){ 
     client = new Socket(serverIp, tcpPort); 

     printStream = new PrintStream(client.getOutputStream()); 
     networkReader = new BufferedInputStream(client.getInputStream()); 

     dataRead = 0; 
     buffer = new byte[1280 * 480]; 
     printStream.println(""); // CR is code to server to send data 


     while(dataRead < (1280 * 480)){ 
      dataRead += networkReader.read(buffer, dataRead, (1280 * 480) - dataRead); 
     } 

     DrawBack d = new DrawBack(); 
     d.execute(); 
     try { 
      d.get(); // here im trying to block main thread purposely 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } catch (ExecutionException e) { 
      e.printStackTrace(); 
     } 

    } 
} 

private class DrawBack extends SwingWorker<Void, Void>{ 

    @Override 
    protected Void doInBackground() throws Exception { 
     byte Y, U, V; 
     int R, G, B, RGB, Yi, Ui, Vi; 
     boolean alternate = false; 
     for(int i = 0; i < 480; ++i){ 
      for(int j = 1; j < 1280; j += 2){ 
       if(alternate){ 
        Y = buffer[i * 1280 + j]; 
        V = buffer[i * 1280 + j -1]; 
        U = buffer[i * 1280 + j -3]; 
       } else { 
        Y = buffer[i * 1280 + j]; 
        U = buffer[i * 1280 + j -1]; 
        V = buffer[i * 1280 + j +1]; 
       } 
       Yi = Y & 0xFF; 
       Ui = U & 0xFF; 
       Vi = V & 0xFF; 

       R = (int)(Yi + 1.402 * (Vi - 128)); 
       G = (int)(Yi - 0.34414 * (Ui - 128) - 0.71414 * (Vi - 128)); 
       B = (int)(Yi + 1.772 * (Ui - 128)); 

       RGB = R; 
       RGB = (RGB << 8) + G; 
       RGB = (RGB << 8) + B; 

       alternate = !alternate; 

       Masapp.window.getImage().setRGB(j/2, i, RGB);// reference to buffered image on JFrame 

       if((i == 100) && (j == 479)){ 
        System.out.println(Yi + " " + Ui + " " + Vi); 
       } 
      } 
     } 
     return null; 
    } 
} 
} 

我甚至试图等待完成与同时:

DrawBack d = new DrawBack(); // DrawBack extends SwingWorker<Void, Void> 
d.execute(); 
while(!d.isDone()); 

,但它并没有改善。当我设置所有像素时,我尝试调用BufferedImage.flush()JFrame.invalidate()

我的问题基本上是:如何定期刷新和显示缓冲图像?

+0

看看http://stackoverflow.com/questions/6319465/fast-loading-and-drawing-of-rgb-data-in-bufferedimage – haraldK

回答

3

您的实施不正确地同步,因为它从工作人员的后台线程而不是event dispatch thread更新GUI。由此产生的行为是不可预知的。相反,请定义一个SwingWorker<BufferedImage, BufferedImage>publish()图像,以便在您的实施process()中稍后进行渲染。为了改善活性,在图像准备好时发布部分图像,例如, publish() a BufferedImage一次只包含一行。比较引用此相关exampleexample以查看该方法。