1

私がやろうとしていることがうまくいくかどうか、または可能かどうかさえわかりません。基本的には、画面を jpeg 画像としてキャプチャし、クライアント アプリに送信して表示するリモート デスクトップ タイプのアプリを作成しています。
以前の画像と比較して差分だけ送信することで、毎回送信するデータ量を減らしたい。例えば:

var bitmap = new Bitmap(1024, 720);

string oldBase = "";

using (var stream = new MemoryStream())
using (var graphics = Graphics.FromImage(bitmap))
{
    graphics.CopyFromScreen(bounds.X, bounds.Y, 0, 0, bounds.Size);
    bitmap.Save(stream, ImageFormat.Jpeg);
    string newBase = Convert.ToBase64String(stream.ToArray());

    // ! Do compare/replace stuff here with newBase and oldBase !

    // Store the old image as a base64 string.
    oldBase = newBase;
}

このようなものを使用して、両方の base64 文字列を比較し、一致するものを置き換えることができました。一致したテキストは、次のようなものに置き換えることができます。

【差し替え文字数】

そうすれば、クライアント側で古いデータを置き換えて新しいデータを追加する場所がわかります。繰り返しますが、これが機能するかどうかはわかりませんので、これについての考えをお寄せください。:) 可能であれば、私を正しい方向に向けていただけますか? ありがとう。

4

3 に答える 3

1

これを行うには、ビットマップ ビットを直接比較します。Bitmap.LockBitsを調べるとBitmapData、ピクセル データを取得できるポインタが得られます。次に、各スキャン ラインのピクセルを比較し、トランスポートに使用する任意の形式にエンコードできます。

スキャン ラインの長さ (バイト単位) は常に 4 の倍数であることに注意してください。したがって、32 ビット カラーを使用している場合を除き、スキャン ラインの最後にあるパディングを考慮する必要があります。それが、構造Stride内のプロパティの目的です。BitmapData

スキャンラインごとに処理を行う方が簡単ですが、ビットマップを 1 つの連続したデータ ブロックとして処理する場合ほど効率的ではない可能性があります (送信されるデータの量を減らすという点では)。トランスポート形式は次のようになります。

<start marker>
// for each scan line
<scan line marker><scan line number>
<pixel position><number of pixels><pixel data>
<pixel position><number of pixels><pixel data>
...
// next scan line
<scan line marker><scan line number>
...
<end marker>

<pixel position><number of pixels><pixel data>エントリは、変更されたピクセルの連続です。スキャン ラインに変更されたピクセルがない場合は、送信しないことを選択できます。または、スキャン ライン マーカーと番号を送信し、その後すぐに次のスキャン ラインを送信することもできます。

<pixel position>フィールドとフィールドには 2 バイトで十分です<number of pixels>。したがって、ブロックごとに 4 バイトのオーバーヘッドがあります。最も単純なバージョンが機能するようになった後、関心のある最適化は、小さな実行がある場合に、変更された/変更されていないピクセルのブロックを結合することです。たとえば、uucucucが変更されuていないピクセルであり、 が変更されたピクセルである場合、を 5 つの変更されたピクセルの 1 つのランとしてcエンコードすることをお勧めします。cucucこれにより、送信する必要があるデータの量が減ります。

これは最善の方法ではありませんが、シンプルで効果的で、比較的簡単に実装できることに注意してください。

いずれにせよ、エンコードが完了したら、データを組み込みのGZipコンプレッサーに通して (あまり役に立たないかもしれませんが)、それをクライアントにパイプでプッシュします。クライアントはデータを解凍し、結果を解釈します。 .

2 つのウィンドウを使用して結果を確認し、1 台のマシンでこれをビルドするのが最も簡単です。それが機能したら、ネットワーク トランスポート部分を接続できます。途中でトランスポート ステップを実行して最初のカットをデバッグすると、非常にイライラすることがあります。

于 2012-09-04T20:32:16.717 に答える
1

現在、非常によく似たものに取り組んでいます。基本的に、実装しようとしているのはビデオ コーデック (非常に単純なモーション jpeg) です。いくつかの単純なアプローチと、いくつかの非常に複雑なアプローチがあります。

  1. 最も簡単な方法は、連続するフレームを比較し、相違点のみを送信することです。RGB 空間または YCbCr 空間でフレーム間の色の違いを比較し、何らかのメタデータで変更されたピクセルのみを送信しようとする場合があります。
  2. より複雑な解決策は、DCT 変換後、エントロピー コーディング前の画像を比較することです。これにより、比較が改善され、醜いアーティファクトが削除されます。
  3. JPEG、Motion JPEG、H.264 の詳細を確認してください。これらのコーデックが使用しているいくつかの方法を使用するか、可能であれば既存のコーデックを使用することができます。
于 2012-09-04T19:59:01.657 に答える
0

これは JPEG では機能しません。BMP、または圧縮されていない TIFF を使用する必要があります。

私だったら、BMP を使用し、ピクセルをスキャンして変更を検出し、変更以外のすべてが透明な PNG を作成すると思います。

まず、PNG 圧縮は特に繰り返しピクセルに対して非常に優れているため、これにより伝送サイズが縮小されます。

第二に、古い画像の上に新しい画像を簡単にペイントできるため、受信側での表示が非常に簡単になります。

于 2012-09-04T19:53:41.297 に答える