2014-01-19 3 views
1

У меня есть BufferedImage, отображаемый в JFrame, который я хочу периодически обновлять с помощью необработанных данных R, G, B, которые я получаю через Socket(byte[] buffer). Последовательность действий должна выглядеть примерно так:Периодически обновляйте 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. Полученное поведение непредсказуемо. Вместо этого определите SwingWorker<BufferedImage, BufferedImage> и publish() изображение для последующего рендеринга в вашей реализации process(). Для улучшения жизнедеятельности публикуйте части изображения по мере их готовности, например. publish() a BufferedImage, содержащий по одной строке за раз. Сравните example, процитированный с этим связанным example, чтобы увидеть подход.

Смежные вопросы