我正在编写一个显示 Map 的程序,并在其上面显示另一个图层,其中显示了摄像机的位置及其查看方向 . Map 本身可以缩放和平移 . 问题是 Map 文件的大小很大,缩放不顺畅 .
我创建了 class ZoomablePictureBox : PictureBox
以添加缩放和平移功能 . 我尝试了不同的方法,从这个和其他论坛,进行缩放和平移,最后得到以下内容,触发 OnPaint
事件的 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提供适当的 Map 平移(计算与此问题无关) .
imgZoomed
是每次缩放更改时在BackgroundWorker中计算的原始 Map 的缩放版本:
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
都是根据当前的缩放计算出来的 . Map 大小约为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);
变焦更平滑,因为从我的理解,它只是拉伸原始图像 . 另一方面,平移正在大量减少 .
我想的是:
-
为内存/硬盘上的每个缩放创建orignial map的副本 - 它将占用太多的内存/硬盘空间
-
为下一个/实际/上一个缩放创建orignial Map 的副本,这样我就有更多的时间来计算下一步 - 如果用户一次滚动多个步骤,它将无济于事
我也试过矩阵变换 - 没有真正的性能提升,而计算平移是一个真正的痛苦 .
我在这里跑圈子,不知道怎么做 . 如果我在默认的Windows图片浏览器中打开 Map ,则缩放和平移是平滑的 . 他们是怎么做到的?
我以什么方式同时实现平滑缩放和平移?
1 回答
对不起,这太长了,我只留下了必要的部分 .
大多数p / invoke东西取自pinvoke.net
我在大图像上平滑平移的解决方案涉及使用
StretchBlt
gdi方法而不是Graphics.DrawImage
. 我创建了一个静态类,它将所有本机blitting操作分组 .另一件有用的事情是缓存
Bitmap
的HBitmap
和Graphics
对象 .