ビットマップ/ラスターソフトウェアは2つのメモリバッファを使用します。1つはユーザーが明示的に変更したピクセルを含む現在の「永続化」キャンバスで、もう1つは画面上にキャンバスを表示するために使用されるグラフィックカードのフレームバッファです。
ビットマップドキュメントを画面に表示するには、メモリ内のビットマップドキュメントの生のバイトをフレームバッファにコピーするだけです(フレームバッファのバイト形式または色深度がメモリ内のビットマップと異なる場合は、次のようにする必要があります。変換を実行します。GDIは必要に応じてこれを実行できますが、すべてが32ビットARGBであると仮定しましょう。
WinFormsでは、フレームバッファはオーバーライドGraphics
に渡された引数によって公開されます。Control.OnPaint
これらの「プレビュー」効果は、次の2つのアプローチのいずれかを使用して実装できます。
モダン
最初のアプローチは今日使用されており、過去17年ほど(Windows 95以降)使用されています。インメモリビットマップは、マウスを1回動かす(1pxでも)など、画面を更新する必要があるときはいつでもフレームバッファにコピーされます。次に、プレビュー効果(ユーザーがマウスボタンを離したときに描画する線など)が上に描画されます。ユーザーのマウスが再び移動するとすぐにこのプロセスが繰り返されるため、プレビューが更新されます。
あなたはこのようなものを持っているでしょう:
public class PaintingCanvas : Control {
private Bitmap _canvas = new Bitmap();
private Boolean _inOp; // are we in a mouse operation?
private Point _opStart; // where the current mouse operation started
private Point _opEnd; // where it ends
public override void OnPaint(PaintEventArgs e) {
Graphics g = e.Graphics;
g.DrawImage( _canvas ); // draw the current state
if( _inOp ) {
// assuming the only operation is to draw a line
g.DrawLine( _opStart, _opEnd );
}
}
protected override OnMouseDown(Point p) {
_inOp = true;
_opStart = _opEnd = p;
}
protected override OnMouseMove(Point p) {
_opEnd = p;
this.Invalidate(); // trigger repainting
}
protected override OnMouseUp(Point p) {
using( Graphics g = Graphics.FromImage( _bitmap ) ) {
g.DrawLine( _opStart, _opEnd ); // a permanent line
}
_inOp = false;
}
}
1980年代のフラッシュブラック
昔(1980年代を考えてください)、メモリからフレームバッファへのビットマップのコピーは遅かったので、驚くほど良いハックはXORペイントを使用していました。プログラムはフレームバッファの所有権を引き継ぎます(したがって、ウィンドウが重なってもメモリからコピーする必要はありません)。プレビューラインは、ラインがカバーするすべてのピクセルのXORを実行することによって描画されます。ピクセルをXORすると、メモリからピクセルを再コピーしなくても元の色を復元できるため、これは高速です。このトリックは、最近まで、さまざまな種類の選択、ハイライト、またはプレビュー効果のためにコンピューターで使用されていました。
highlightOrPreviewColor = originalPixelColor XOR (2^bpp - 1)
originalPixelColor = highlightOrPreviewColor XOR (2^bpp - 1)