私のプログラムでは、基本的な画像エディターをコーディングしています。これにより、ユーザーは長方形の領域を描くことができ、その領域が 3 倍程度にズームされた表示がポップアップ表示されます (マウス ホイールでさらに調整できます)。この画像を右クリックしてドラッグすると、元の画像上でズーム領域が移動し、基本的に虫眼鏡のように機能します。
問題は、比較的小さなビットマップでも重大なパフォーマンスの問題が発生することです。ズームされた領域を示すビットマップが約 400x400 の場合、マウスが動くのと同じくらい速く更新され、完全に滑らかですが、マウス ホイールでズームを約 450x450 まで上げると、すぐにチャンクが開始され、1 秒あたり約 2 回の更新になります。もしそうなら。なぜこのようなわずかな増加が大きなパフォーマンスの問題を引き起こすのか理解できません...内部メモリの制限か何かに達したようです。ズームされているソースビットマップのサイズは問題ではないようです。ズームされたビットマップのサイズだけです。
問題は、Graphics.DrawImage と PictureBox を使用していることです。このサイトを読んでみると、通常、これらの両方のパフォーマンスがあまり良くないことがわかりますが、スピードを改善するための GDI の内部動作について十分に知りません。私のボトルネックがどこにあるかを知っている人がいるといいのですが、私はおそらくこれらのツールを不適切な方法で使用しているか、代わりに使用するより良いツールを知らないからです。
これは、私のマウス イベントと関連する関数の一部です。
private void pictureBox_MouseDown(object sender, MouseEventArgs e)
{
else if (e.Button == System.Windows.Forms.MouseButtons.Right)
{
// slide the zoomed part to look at a different area of the original image
if (zoomFactor > 1)
{
isMovingZoom = true;
// try saving the graphics object?? are these settings helping at all??
zoomingGraphics = Graphics.FromImage(displayImage);
zoomingGraphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighSpeed;
zoomingGraphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Low;
zoomingGraphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighSpeed;
zoomingGraphics.PixelOffsetMode = PixelOffsetMode.HighSpeed;
}
}
}
private void pictureBox_MouseMove(object sender, MouseEventArgs e)
{
if (isMovingZoom)
{
// some computation on where they moved mouse ommitted here
zoomRegion.X = originalZoomRegion.X + delta.X;
zoomRegion.Y = originalZoomRegion.Y + delta.Y;
zoomRegionEnlarged = scaleToOriginal(zoomRegion);
// overwrite the existing displayImage to prevent more Bitmaps being allocated
createZoomedImage(image.Bitmap, zoomRegionEnlarged, zoomFactor, displayImage, zoomingGraphics);
}
}
private void createZoomedImage(Bitmap source, Rectangle srcRegion, float zoom, Bitmap output, Graphics outputGraphics)
{
Rectangle destRect = new Rectangle(0, 0, (int)(srcRegion.Width * zoom), (int)(srcRegion.Height * zoom));
outputGraphics.DrawImage(source, destRect, srcRegion, GraphicsUnit.Pixel);
if (displayImage != originalDisplayImage && displayImage != output)
displayImage.Dispose();
setImageInBox(output);
}
// sets the picture box image, as well as resizes the window to fit
void setImageInBox(Bitmap bmp)
{
pictureBox.Image = bmp;
displayImage = bmp;
this.Width = pictureBox.Width + okButton.Width + SystemInformation.FrameBorderSize.Width * 2 + 25;
this.Height = Math.Max(450, pictureBox.Height) + SystemInformation.CaptionHeight + SystemInformation.FrameBorderSize.Height * 2 + 20;
}
private void pictureBox_MouseUp(object sender, MouseEventArgs e)
{
else if (e.Button == System.Windows.Forms.MouseButtons.Right)
{
if (isMovingZoom)
{
isMovingZoom = false;
zoomingGraphics.Dispose();
}
}
}
ご覧のとおり、何かを描画するたびに新しい Bitmap を宣言するのではなく、古い Bitmap (および Bitmap のグラフィックス オブジェクト) を再利用していますが、Graphics. FromImage を繰り返し)。コードをベンチマークするためにストップウォッチを追加しようとしましたが、DrawImage は機能を別のスレッドに渡すため、関数は比較的迅速に実行されると主張しています。Dispose
Bitmap オブジェクトと Graphics オブジェクトを使用していないときはすべて使用しようとしており、MouseMove
イベント中にリソースの割り当て/割り当て解除を繰り返し呼び出さないようにしています。を使用してPictureBox
いますが、ここでは問題ないと思います。
このコードをスピードアップしたり、DrawImage で何が起こっているかを教えていただければ幸いです。見栄えを良くするために余分なコードを削除しましたが、誤って重要なものを削除したり、問題を引き起こしている可能性のあるものの使用方法を示していない場合は、お知らせください。役職。