我正在编写一个程序,用于显示地图,叠加在地图上的是摄像机位置及其视角的另一层。地图本身可以缩放和平移。问题在于地图文件大小相当大,缩放不流畅。
我创建了一个名为
Zoom是更加流畅的,因为据我所知,它只是拉伸原始图像。另一方面,平移会跳跃严重。
我想过:
创建每个缩放级别的原始地图副本存储在内存/硬盘中 - 这将占用太多的内存/硬盘空间。
为下一个/当前/前一个缩放级别创建原始地图的副本,以便我有更多时间计算下一步 - 如果用户一次滚动多个步骤,则这种方法将无济于事。
我也尝试了矩阵变换 - 没有真正的性能提升,并且计算平移真的很麻烦。
我陷入了困境,不知道该怎么做。如果我在默认的Windows图片查看器中打开地图,缩放和平移就会很平滑。他们是如何做到这一点的呢?
如何同时实现平稳的缩放和平移?
我创建了一个名为
ZoomablePictureBox : PictureBox
的类,以添加缩放和平移功能。我尝试了来自此处和其他论坛的不同方法进行缩放和平移,并最终得出以下结论,触发ZoomablePictureBox
的OnPaint
事件: private void DrawImgZoomed(PaintEventArgs e)
{
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
if (imgZoomed != null)
e.Graphics.DrawImage(imgZoomed, new Rectangle(-ShiftX, -ShiftY, imgZoomed.Width, imgZoomed.Height), 0, 0, imgZoomed.Width, imgZoomed.Height, GraphicsUnit.Pixel);
}
ShiftX和ShiftY提供适当的地图平移(对于此问题无关)。
imgZoomed
是原始地图的缩放版本,每次缩放更改时在BackgroundWorker中计算:
private void bgWorker_DoWork(object sender, DoWorkEventArgs e)
{
Bitmap workerImage = e.Argument as Bitmap;
Bitmap result;
result = new Bitmap(workerImage, new Size((int)(workerImage.Width * Zoom), (int)(workerImage.Height * Zoom)));
e.Result = result;
}
目前的做法是,每次用户滚动鼠标,都会根据当前缩放计算新的imgZoomed
。由于地图大小约为30 MB,这可能需要长达0.5秒的时间,这很烦人,但平移运行平稳。
我意识到这可能不是最好的想法。在以前的方法中,我没有在每次滚动鼠标时创建缩放后的图像副本,而是这样做:
e.Graphics.DrawImage(Image, new Rectangle(-ShiftX, -ShiftY, (int)(this._image.Width * Zoom), (int)(this._image.Height * Zoom)), 0, 0, Image.Width, Image.Height, GraphicsUnit.Pixel);
Zoom是更加流畅的,因为据我所知,它只是拉伸原始图像。另一方面,平移会跳跃严重。
我想过:
创建每个缩放级别的原始地图副本存储在内存/硬盘中 - 这将占用太多的内存/硬盘空间。
为下一个/当前/前一个缩放级别创建原始地图的副本,以便我有更多时间计算下一步 - 如果用户一次滚动多个步骤,则这种方法将无济于事。
我也尝试了矩阵变换 - 没有真正的性能提升,并且计算平移真的很麻烦。
我陷入了困境,不知道该怎么做。如果我在默认的Windows图片查看器中打开地图,缩放和平移就会很平滑。他们是如何做到这一点的呢?
如何同时实现平稳的缩放和平移?
Graphics
和HBitmap
对象以及StretchBlt
可以获得迄今为止最流畅的性能。这帮助我在7000X7000像素的图像上实现了超级流畅的显示。 - Rotem