2015-10-07 50 views
0

我將給出一個小小的介紹:我在c#上使用一個小屏幕共享項目,並使用Tcp Protocol來發送數據。基本上我叫GDI的BitBlt方法,它的工作非常好。在我第一次發送整個緩衝區,然後我迭代並只發送更改的像素。 在我發送緩衝器中的每個字節表示(在RGBA順序)的組件 - 這是一個簡單的例子小的陣列:C#減少網絡帶寬使用

byte[] pixelarray = { 45, 201, 173,1 }; 
//R=45,G=201,B=173,Alpha=1(always 1 on screen). 

允許繼續前進。 我的屏幕是1920x1080(在我的情況)所以實際上1920x1080x4(每個像素是4字節)=高達8,294,400像素。 使用Gzipstream這樣的壓縮將大小減小到〜250kb。這是我第一次發送的內容。之後,我只是比較每個BitBlt捕獲的字節數組,並只發送已更改的像素。它看起來像這樣:

public void StartAsync(ScreenFrame frame) 
    { 
     using (var memoryStream = new MemoryStream()) 
     {  
      for (var i = 0; i < frame.NewPixels.Length; i += 4) 
      { 
        memoryStream.WriteByte(frame.NewPixels[i]); 
        memoryStream.WriteByte(frame.NewPixels[i + 1]); 
        memoryStream.WriteByte(frame.NewPixels[i + 2]);   
      } 

      byte[] data = compress(memoryStream.ToArray());//compress gzip. 
      SendVarData(data);//this is a simple function to send it on a socket. 

     } 
    } 


    public void DeltaAsync(ScreenFrame frame) 
    { 
     using (var memoryStream = new MemoryStream()) 
     { 
      for (var i = 0; i < frame.NewPixels.Length; i += 4)//loop through buffers and write only differnt bytes. 
     { 
      if (frame.NewPixels[i] == frame.PreviousPixels[i] && 
       frame.NewPixels[i + 1] == frame.PreviousPixels[i + 1] && 
       frame.NewPixels[i + 2] == frame.PreviousPixels[i + 2]) 
       continue; 
      memoryStream.Write(BitConverter.GetBytes(i), 0, 4);//write the index. 
      memoryStream.WriteByte(frame.NewPixels[i]); 
      memoryStream.WriteByte(frame.NewPixels[i + 1]); 
      memoryStream.WriteByte(frame.NewPixels[i + 2]); 
      } 
      byte[] buff = compress(memoryStream.ToArray());//compress gzip. 
      SendVarData(buff); 
     } 
    } 

處理和應用在對方的變化不是我的主要問題。 我真正的瓶頸是帶寬使用。在桌面上的一個小的變化,例如,當用戶使用右鍵點擊鼠標他並打開經典的菜單,發送的數據是(壓縮後!)約120〜150KB! 我真的喜歡去優化它。我不能讓我的程序通過網絡發送大量數據時,有隻有一個小的變化... 正如你看到的,我已經使用

  • 一個gzip壓縮(其提供高壓縮比)。

  • 只寫差異。

    進出口尋找方法來優化網絡的想法...我會非常非常appreicate因爲即時通訊的任何傳入幫助打破我的頭相當長的時間,並試圖想想財產以後可以幫助...

謝謝。

+0

聽起來很像一個簡單的RFB實現​​,你看着現有的開源VNC客戶端? –

+0

有一件事你可以做的是「試」檢測連續色塊和發送「黑白200x100灰色矩形」這你可以在幾個字節,而不是60K(壓縮前) –

回答

1

對屏幕的更改通常會影響矩形塊中的所有(或大部分)字節。您的壓縮效率較低(與其他遠程查看器應用程序相比),因爲它沒有考慮到這一點。一種方法是嘗試確定已經改變的區域的邊界,然後發送整個用png之類壓縮的區域。但是你真的應該研究png和其他圖像壓縮算法對2d數據執行的變換,以使它們更加可壓縮。

變換是對數據壓縮步驟之前應用的圖像數據的可逆操作,旨在使數據更具可壓縮性。一種變換可能是從上面一行中的像素中減去像素值。如果圖像從一行到另一行的變化不大,則會從中得到大量的零,這將比每行的實際像素數據更具可壓縮性。

+0

沒關係..感謝..但是你的意思是什麼壓縮像png這樣的東西? :) – Slashy

+0

@Slashy - 創建一個代表圖像變化部分的位圖,並將其保存爲一個.png(或者如果您可以忍受壓縮工件,則將其保存爲.jpg) - 這是一種天真的方法。在關於該問題的評論中關於查看VNC實現的源代碼的建議也很好。 – antlersoft

+0

我會考慮vnc ..(首先我應該罰款它的鏈接哈哈,這是我第一次)。關於你的想法,它與我所做的相似..從圖像中裁剪並保存到內存中,因爲png就是我所做的......你知道如何存儲png嗎?它是一個rgba字節數組,它與gzip兼容......所以我沒有看到有任何理由這樣做......(沒有提到查找不同區域和每次發送區域(可以是一個圖像上的某些不同區域)的複雜性)) 。 – Slashy