在我的程序中,我正在编写一个基本的图像编辑器。其中一部分允许用户绘制一个矩形区域,然后我弹出一个显示,显示该区域缩放了 3 倍左右(他们可以使用鼠标滚轮进一步调整)。如果他们右键单击并拖动此图像,它将在原始图像上移动缩放区域,基本上充当放大镜。
问题是,即使在相对较小的位图上,我也看到了一些严重的性能问题。如果显示缩放区域的位图在 400x400 左右,它的更新速度仍然与鼠标移动的速度一样快,并且非常平滑,但是如果我将鼠标滚轮缩放到 450x450 左右,它会立即开始分块,每秒只有大约 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();
}
}
}
正如你所看到的,我不是每次想要绘制东西时都声明一个新的位图,我正在重用一个旧的位图(以及位图的图形对象,尽管我不知道调用 Graphics. FromImage 反复)。我尝试添加秒表来对我的代码进行基准测试,但我认为 DrawImage 将功能传递给另一个线程,因此该函数声称可以相对快速地完成。Dispose
当我不使用它们时,我会尝试使用所有的 Bitmap 和 Graphics 对象,并避免在MouseMove
事件期间重复调用来分配/取消分配资源。我正在使用 aPictureBox
但我认为这不是问题所在。
任何帮助加速此代码或教我 DrawImage 中发生的事情都非常感谢!我修剪了一些多余的代码以使其更美观,但如果我不小心修剪了一些重要的东西,或者没有展示我如何使用可能导致问题的东西,请告诉我,我会修改邮政。