2009-05-30 17 views
5

リアルタイムで更新するグラフを描画したい(右から増やす)。私が考えることができる最も効果的な方法は、x [0 .. width-2]から1ピクセルだけ残したすべてをコピーし、x [width-1]に新しい値を描画することです。Android:効率的にキャンバスの内容をスクロールしますか?

私はAndroidでの経験はほとんどありませんが、私が知る限り、Canvasはその内容について全く動作しません。毎回画面全体を再描画する必要がありますか?これはスケーリングとスムージングが必要なので、私はそれが遅くなることを心配しています。

バイト[] []に描画する必要があります。これを使用して画面にペイントします(毎回バッファの内容を移動します)。

+0

私はBitmap、getPixels、setPixelsを使用して、考えられるアプローチがあると思います。これが悪いアプローチであるかどうかはわかりませんが、私はそれに挑戦しています。お知らせ下さい! –

答えて

0

あなたはすでに考えているかもしれないが、私はバッファの内容をシフトしないだろう - 私は循環バッファのように使ってみよう。現在の列のインデックスを保持し、もう一度左端の列に折り返したら、現在の列の右側にあるものと左側にあるものの2つのセグメントで目的地に描画できます。最後に塗りつぶされた列。この方法では、何かをシフトする必要はなく、各画面のリフレッシュは2つのセグメントの2つのブリット(ビットマップコピー)です。そのビットが遅すぎると、一度に画面全体にブリッジする前に、それらを常に2番目のオフスクリーンバッファにペイントすることができます。確かに画面に大きなblitはかなり速いですか?

+0

また、私は言及するのを忘れてしまったこともあります(これはまた、はっきりと考えるかもしれませんが、あなたが知っていることは分かりませんので、私を許してください) - 私はあなたのバッファイメージがサイズに合わせてあなたが描画したい画面領域の大きさと、グラフ描画の小さな部分をスケーリングします。その結果、大きなブライトを行うと、ソースとデスティネーションが可能な限り一致します(高さとビットマップ形式は同じです)。スケーリングが必要です。 – themightyjon

1

グラフがバインドされている場合は、すべての画像を一度画像にレンダリングしてから、その画像から関連する部分をキャンバスにblitしてみてください。バッファ内のピクセルを実際に「移動」させないようにしてください。読み取りと書き込みの依存関係が発生し、パフォーマンスが大幅に低下する可能性があります。実際には、1つのバッファから別のバッファにコピーして、それを画面にブリットさせるのが良いかもしれません。最後に、手動でピクセルを処理する必要が生じた場合は、列ではなく行でイメージを実行し、行の先頭からキャッシングを開始するようにしてください。

1

パフォーマンスに関しては、プロファイリングなしではわかりません。

あなたのターゲット電話でハードウェアアクセラレーションが行われている可能性があります。また、各フレームのライン描画プリミティブを使用してゼロからグラフを描画する必要があります。一方

、画像バッファの直接的な画素の操作は次のようになります

する適切なサイズの画像を作成し、「background_color」にそれをオフにします。この画像にはsetpixel()機能が必要です。

各x時間のyを記録する値の配列を持っているので、どの列でも最後にグラフをプロットした場所を知ることができます。

"chart_image"と "chart_array"を循環バッファとして扱います。各タイムステップごとに:

Y = ...; 
X = time_since_start % chart_width; 
chart_image.setpixel(X,chart_array[X],background_color); // clear previous line 
chart_array[X] = Y; 
chart_image.setpixel(X,chart_array[X],foreground_color); // draw new plot 

そして、あなたはそれをblitする必要があります。あなたではなく、個々のピクセルよりもラインを使用したい場合は

X = time_since_start % chart_width; 
// the newest data is on the left of the chart_image but gets drawn on the right side of the output 
blit(out_x+X,out_y, // destination coordinates 
    chart_image, 
    0,0, // top left of part of chart_image to blit 
    X,chart_height); // bottom right of chart_image part 
// the oldest data is on the right of the chart_image but gets drawn on the left side of the output 
blit(out_x,out_y, 
    chart_image, 
    X,0, 
    chart_width,chart_height); 

物事をよりトリッキー取得し、代わりにsetpixel()drawline()もこのアプローチでその仕事をすることができます:あなたは二度画像をブリットする必要があります。

(Android APIを知らないことに対する謝罪ですが、そのアプローチは一般的です。)

0

グラフデータをメモリに格納しているとは思うので、再描画しても問題にはなりません。フレームごとにポイントのセットを再描画することは、集中的なことではありません。メモリを移動することは集中的であり、必要なものだけをペイントするのではなく、すべてを動かしています。 時間の関数である最悪のシナリオでは、ディスプレイの列ごとに1つの値しかありません。システムが描画する必要があるランドスケープ内の800ピクセル/値をaproxにします。それは簡単です。 これをプロファイルしましたか? 編集:システムが各点を描画しなければならないということではなく、メモリ上に描画するだけで、プリミティブを使用します。ポイントを描画してビデオメモリにダンプしてから、もう一度やり直すようには思わないでください。

関連する問題