2012-12-08 17 views
5

ServerSocket'ın ImageIO.write (....) kullanarak bir görüntü akışı gönderebilmesi için bir ServerSocket ve bir Prizim kuruluyor ve Socket bunları okumak ve bir JFrame'i bunlarla güncellemeye çalışır. Bu yüzden ImageIO'nun bir resmin sonunu tespit edip edemeyeceğini merak ettim. (Kesinlikle JPEG formatını bilmiyorum, bu yüzden onu test ettim)ImageIO kullanarak bir görüntü akışı gönder?

Görünüşe göre, değil.

Sunucu tarafında, aralarında biraz uyku ile ImageIO.write (...) kullanarak resimleri sürekli olarak gönderdim. İstemci tarafında, ImageIO ilk görüntüyü okumadı, fakat bir sonraki sayfada boş döndü. Bu kafa karıştırıcı. İlk görüntüyü okumayı engellemeyi bekliyordum (çünkü bir sonraki görüntünün hala aynı resmin parçası olduğunu düşünüyor) ya da hepsini okumada başarılı (çünkü işe yarıyor). Ne oluyor? ImageIO, ilk görüntünün sonunu değil, ikinci görüntüyü algılar gibi görünüyor. (Bu arada, görüntüler birbiriyle kabaca birbirine benzemektedir.) Bu gibi görüntüleri akıtmanın kolay bir yolu var mı, yoksa baytları bir bayt veya bir dizi diziye ulaşana kadar bir arabelleğe geçiren kendi mekanizmamı yapmak zorunda mıyım? bayt, hangi noktada arabellekten görüntüyü okur?

yararlıdır benim sunucu kod parçasıdır:

 while(true){ 
      Socket sock=s.accept(); 
      System.out.println("Connection"); 
      OutputStream out=sock.getOutputStream(); 
      while(!socket.isClosed()){ 
       BufferedImage img=//get image 
       ImageIO.write(img, "jpg", out); 
       Thread.sleep(100); 
      } 
      System.out.println("Closed"); 
     } 

Müvekkilim kodu:

 Socket s=new Socket(InetAddress.getByName("localhost"), 1998); 
     InputStream in=s.getInputStream(); 
     while(!s.isClosed()){ 
      BufferedImage img=ImageIO.read(in); 
      if(img==null)//this is what happens on the SECOND image 
      else // do something useful with the image 
     } 
+0

Daha da kötüsü: ImageIO.write biçimini png olarak ayarlıyorum ve işe yaradı (bir dereceye kadar. Alınan görüntülerin yarısı null) – DankMemes

+0

Her şeyden önce arabellek sistemini uygulamak zorunda kalacağım gibi görünüyor. :( – DankMemes

+1

* "ImageIO.write (....) kullanarak görüntü akışı ve Soket bunları okumak ve bir JFrame'i bunlarla güncellemeye çalışır." * Bu, web sohbeti veya ekran paylaşımı veya benzerleri içinse, not Video akışları ya da akıllıca en aza indirgenmiş görüntüler (örneğin, sadece bir değiştirilen alanın bir ekimine yönelik bir ekran) gerektirdiği gibi, tek tek görüntüler göndermek sonuçlanan videonun bir buzul gibi yayılmasına neden olacaktır (Küresel İklim Değişikliğini göz ardı ederek). –

cevap

4

ImageIO.read(InputStream) bir ImageInputStream yaratır ve içten read(ImageInputStream) çağırır. Bu ikinci yöntem, görüntüyü okurken bittiğinde akışı kapatmak için belgelenmiştir.

Yani, teoride, sadece ImageReader alabilirsiniz kendiniz bir ImageInputStream oluşturmak ve tekrar tekrar ImageInputStream den ImageReader okuma var. Bir ImageInputStream, tek ve tek bir görüntü ile çalışmak üzere tasarlandı (birden çok kare içerebilir veya içermeyebilir). ImageReader.read(0)'u bir kereden fazla çağırırsanız, her seferinde (önbelleğe alınmış) akış verilerinin başına geri döner ve aynı görüntüyü tekrar tekrar verir. ImageReader.read(1), çok çerçeveli bir görüntüde ikinci bir çerçeve arar, ki bu elbette JPEG ile hiçbir anlam ifade etmez.

Belki bir ImageInputStream oluşturabiliriz, ImageReader'ı buradan okuyabilir ve ardından akıştaki sonraki görüntü verilerini işlemek için yeni bir ImageInputStream oluşturabiliriz, değil mi? Bunun dışında, ImageInputStream'un her türlü önbelleğe alma, okuma-ileri ve geri itme özelliği vardır, bu da sarılmış InputStream öğesinin okuma konumunu bilmeyi zorlaştırır. Bir sonraki ImageInputStream bir yerden veri okumaya başlar, ancak ilk görüntünün verilerinin sonunda beklediğimiz gibi olmaz.

Temel akışınızın konumundan emin olmanın tek yolu mark ve reset. Resimler büyük olabileceğinden, büyük bir readLimit'a izin vermek için muhtemelen bir BufferedInputStream gerekir.

Bu

benim için çalıştı: belki de en uygun yolu bunu yapmak iken

private static final int MAX_IMAGE_SIZE = 50 * 1024 * 1024; 

static void readImages(InputStream stream) 
throws IOException { 
    stream = new BufferedInputStream(stream); 

    while (true) { 
     stream.mark(MAX_IMAGE_SIZE); 

     ImageInputStream imgStream = 
      ImageIO.createImageInputStream(stream); 

     Iterator<ImageReader> i = 
      ImageIO.getImageReaders(imgStream); 
     if (!i.hasNext()) { 
      logger.log(Level.FINE, "No ImageReaders found, exiting."); 
      break; 
     } 

     ImageReader reader = i.next(); 
     reader.setInput(imgStream); 

     BufferedImage image = reader.read(0); 
     if (image == null) { 
      logger.log(Level.FINE, "No more images to read, exiting."); 
      break; 
     } 

     logger.log(Level.INFO, 
      "Read {0,number}\u00d7{1,number} image", 
      new Object[] { image.getWidth(), image.getHeight() }); 

     long bytesRead = imgStream.getStreamPosition(); 

     stream.reset(); 
     stream.skip(bytesRead); 
    } 
} 
0

Aşağıdaki kod senin sahip konuya geçmiş almak istiyorum. Önceki bir cevap olarak ImageIO, resmin sonunda akıştan ayrılmadığını kaydetti, bu bir sonraki resme giden yolu bulacaktır.

int imageCount = in.read(); 
for (int i = 0; i < imageCount; i ++){ 
    BufferedImage img = ImageIO.read(in); 
    while (img == null){img = ImageIO.read(in);} 
    //Do what ever with img 
} 
İlgili konular