1

C ++と.netを使用して、スクロール画像として表示したいデータのストリームがあります。新しいデータを取得するたびに、それを新しい行(128x1ピクセル)として追加し、前のコンテンツを片側にスクロールします。

この問題を最初に突き止めたのは、新しい行を取得するたびにデータセット全体をレンダリングすることでした。これは機能しましたが、遅すぎたので、ある種のバッファ(ビットマップかもしれません)に書き込む方が理にかなっているのではないかと思います。問題は、どうすればそれができるかわからないことです。オブジェクトを使用すると非常に楽しく描画できますが、オブジェクトをバッファとしてGraphic使用するようにコントロールに指示する明確な方法がわかりませんか?Bitmap同様に、ビットマップに描画して画面に書き込む方法がわかりません。

これは可能であるに違いありませんが、私のgoogle-fooはこれまでのところ失敗しています...

[編集1]明確にするために、データはスペクトログラムです。次の画像は、私が達成しようとしていた種類のことを示しています。

代替テキストhttp://www.geekops.co.uk/photos/0000-00-02%20(Forum%20images)/ScrollingGraphicsAlgorithmExplanation.png

私がプロットしているデータは、floatの配列で提供されます。取得する数を制限するものは何もないので、データがプロットの横から落ちるので、データを忘れたいだけです。

私は現在、から継承してSystem::Windows::Forms::UserControlいますが、より良い代替手段があれば、他のものに切り替えることができますか?

4

5 に答える 5

5

ScrollWindowwin32メソッドを見てください。画面上の既存のデータをスクロールして、新しいデータのみを描画できます。これは非常に高速です。

于 2009-06-28T22:34:54.563 に答える
1

ビットマップbmpImage=new Bitmap(512,512);

for(int iRow = 0; iRow <512; iRow ++)

{{

  for (int iCol = 0; iCol <512; iCol++)
                        {
                            Color clr;
                            bmpImage.SetPixel(iCol, iRow, clr);
                        }

}

(画像)bmpImage.save()

于 2009-07-28T09:25:44.423 に答える
1

考えられる戦略:

  • 左から右にバックバッファを描画します。これは、最後に到達したときに折り返されます。画面にペイントする場合にのみスクロールロジックを実行します(指定されたフレームレートで)。これを実現するには、ソース長方形と宛先長方形でDrawImageを使用します。

  • ビットマップ.LockBits(...)およびbitmap.UnlockBits(...)メソッドを使用して、生のビットマップデータを変更します。これらの関数は実際にはアンマネージメモリからマネージメモリにビットマップデータのコピーを作成するため、変更する長方形のみをロックするように注意してください。これを行う方法の例は、ここで説明されていますBitmap .. ::。LockBitsメソッド(Rectangle、ImageLockMode、PixelFormat)

  • LockBitsの代わりに、ビットマップでSetPixelを使用することもできます。しかし、SetPixelは遅いことが知られています。

  • 画像を画面にブリットするときは、GraphicsインスタンスのCompositingModeがbmpg.CompositingMode = CompositingMode.SourceCopyに設定されていること、およびバックバッファーのピクセル形式がPixelFormat.Format32bppPArgbであることを確認してください。
于 2009-08-07T12:08:06.667 に答える
0

何を描画しようとしているのか(ダイアログのある種のコントロール?)はよくわかりませんが、推測では次のように機能するはずです。

class Foo {
    ...
    Gdiplus::Bitmap* m_pBitmap;
};

void Foo::DrawItem(LPDRAWITEMSTRUCT lpDraw) {

   // update bitmap if needed
   if(some_condition_requiring_bitmap_redraw) {

       // do expensive drawing into bitmap
       Gdiplus::Graphics graphics(m_pBitmap);
   }


   // create a graphics object to draw the control from the bitmap
   Gdiplus::Graphics graphics(lpDraw->hDC);
   graphics.DrawImage(m_pBitmap, ...);
}

とにかく、それは非常に大まかな推測です。.NETを使用している場合(私はそれに慣れていません...)、DrawItem呼び出しはまったく異なるように見えるかもしれませんが、基本的なロジックはほぼ同じである必要があります。

データが正確に何であるかによっては、一度に1ピクセルの行を描画するのは効率的でない場合があります。大きな領域を描画し、必要に応じてその一部のみを表示する方がよい場合がありますが、それは明らかにデータの入力方法によって異なります。

また、コンテンツを「スクロール」するために、ビットマップになんらかの更新を行う必要がある場合もあります。それはあなたにお任せします:-)

于 2009-06-28T22:50:59.150 に答える
0

次のことを試してください。

  • 新しいVC++WinFormsアプリケーションを起動します。
  • 「スペクトログラム」という名前のユーザーコントロールをプロジェクトに追加します
  • 'Spectrogram'ユーザーコントロールにタイマーコントロールを追加し、'Enabled'プロパティをtrueに設定します
  • 次のプライベート変数を「スペクトログラム」ユーザーコントロールに追加します
private:
Graphics ^m_gfxBuffer;
Graphics ^m_gfxOriginal;
Bitmap ^m_bmpBuffer;
Bitmap ^m_bmpOriginal;
  • 次のコードを「スペクトログラム」コンストラクターに追加します。

m_bmpBuffer = gcnew Bitmap(this->ClientSize.Width, this->ClientSize.Height);
m_gfxBuffer = Graphics::FromImage(m_bmpBuffer);
m_bmpOriginal = gcnew Bitmap(this->ClientSize.Width, this->ClientSize.Height);
m_gfxOriginal = Graphics::FromImage(m_bmpOriginal);
this->SetStyle(::ControlStyles::AllPaintingInWmPaint | ::ControlStyles::DoubleBuffer | ::ControlStyles::UserPaint | ::ControlStyles::OptimizedDoubleBuffer, true);
this->UpdateStyles();
  • 次のコードを「スペクトログラム」ペイントイベントに追加します。

array<unsigned char, 1> ^bytes = gcnew array<unsigned char, 1>(m_bmpBuffer->Height * 3);
Random ^r = gcnew Random();
r->NextBytes(bytes);

m_gfxOriginal->DrawImage(m_bmpBuffer, -1, 0);

int y = 0;
for (int i = 0; i < m_bmpOriginal->Height * 3; i += 3)
{
  m_bmpOriginal->SetPixel(m_bmpOriginal->Width - 1, y++, ::Drawing::Color::FromArgb(255, bytes[i], bytes[i + 1], bytes[i + 2]));
}

m_gfxBuffer->DrawImage(m_bmpOriginal, 0, 0);
e->Graphics->DrawImage(m_bmpOriginal, 0, 0);    
  • 次のコードを追加します。「スペクトログラム」タイマーティックイベント

this->Invalidate(false);
  • プロジェクトを保存します
  • クリーンアップして再構築
  • プロジェクトを実行する
  • 実行中のフォームを閉じる
  • これで、スペクトログラムのユーザーコントロールが「ツールボックス」に表示されます。
  • それを「ツールボックス」からフォームにドラッグすると、ランダムな色のスペクトログラムがスクロールして表示されます。

これにより、ビットマップバッファコントロールの概要がわかります。ここで重要なのは、コンストラクターでの「SetStyle」呼び出しと、paintイベントでのビットマップの-1によるオフセットです。

グラフィックスとビットマップオブジェクトを適切に破棄し、サイズ変更イベントでそれらを破棄して再構築する必要があります。

お役に立てれば。どうなるか教えてください。

于 2009-06-29T02:04:58.803 に答える