裁剪图像而不复制

5

我正在编写一款需要将大图像分割为小块的应用程序,其中每个块本质上都是原始图像的裁剪版本。

目前,我的分割操作大致如下:

tile.Image = new BitmapImage();
tile.Image.BeginInit();
tile.Image.UriSource = OriginalImage.UriSource;
tile.Image.SourceRect = new Int32Rect(x * tileWidth + x, y * tileHeight, tileWidth, tileHeight);
tile.Image.EndInit();

直觉上,我认为这将基本上创建一个对原始图像的“引用”,并且只会显示为图像的子矩形。然而,我的分割操作执行速度缓慢使我相信,这实际上是复制了原始图像的源矩形,对于大型图像来说非常慢(当分割一个相当大的图像时,会有明显的3-4秒暂停)。
我稍微查看了一下,但没有找到一种在不复制任何数据的情况下将位图绘制为大图像的子矩形的方法。有什么建议吗?

你尝试过创建一个新的“Bitmap”并将其混合吗?我认为这可能比尝试内联裁剪图像更快。 - Mike Caron
你的tile类可以存储对原始图像的引用和在绘制自身时要复制的矩形吗? Graphics.DrawImage有重载方法,可用于绘制位图的一部分:http://msdn.microsoft.com/zh-cn/library/3tf158xz.aspx - Blorgbeard
我承认在图像处理方面不是专家,但我不确定你所要求的是否有意义。虽然可能有一种机制来隐藏副本,但我怀疑无论如何都需要在内存中“重新对齐”(复制)图像数据。 - svidgen
澄清一下我的上一个评论,我只是在考虑内部存储格式——很可能只是一个字节数组。简化了很多,例如,一个4x4的图像在内存中是ABCD EFGH IJKL MNOP。如果你想要左上角的2x2,你需要一个新的字节数组,比如ABEF。这不是一个子数组。 - svidgen
我已经编辑了你的标题。请查看"问题的标题应该包含“标签”吗?",在那里达成共识是“不应该包含”。 - John Saunders
Graphics.DrawImage是一个不错的建议,但不幸的是我的绘制发生在XAML中,通过绑定的BitmapImages进行,因此我认为我对此没有控制。接下来要尝试的可能是Mike的建议。 - phosphoer
1个回答

4
使用System.Windows.Media.Imaging.CroppedBitmap类:
// Create a CroppedBitmap from the original image.
Int32Rect rect = new Int32Rect(x * tileWidth + x, y * tileHeight, tileWidth, tileHeight);
CroppedBitmap croppedBitmap = new CroppedBitmap(originalImage, rect);

// Create an Image element.
Image tileImage = new Image();
tileImage.Width = tileWidth;
tileImage.Height = tileHeight;
tileImage.Source = croppedBitmap;

1
之前我曾评论说这并没有显著提高性能,但是我又尝试了一遍旧方法,确实产生了显著的性能提升(从分割近6秒变成了大约1秒)。 - phosphoer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接