使用WriteableBitmap在Silverlight 3中调整图像大小

5
这是我开始接触Silverlight的第一天。我试图原型化一个应用程序,其中(除了其他功能)应该能够调整大小用户提供的图像。它应该能够处理和显示多个调整大小后的图像。我已经尝试的最明显的方法似乎会“泄漏”内存,因为原始位图仍然以某种方式被引用,这会导致Silverlight在一段时间后分配数百兆字节的内存。我只想能够逐个加载图像,将它们调整大小并保留小版本。
确切地说,我已经尝试了以下方法:
- 创建 System.Windows.Controls.Image 列表(并进行缩放)。我并不惊讶这没有起作用。 - 创建由图像画刷填充的矩形列表。我也不感到惊讶。 - 将位图渲染成 System.Windows.Media.Imaging.WriteableBitmap。我预计这将执行良好;我认为位图实际上是直接绘制的,而没有以任何方式引用。然而,内存消耗表明情况并非如此。
下面是相关代码的一部分:
// create image source
Stream stream = file.OpenRead();
BitmapImage bmpImg = new BitmapImage();
bmpImg.SetSource(stream);
stream.Close();

// create temporary image from it
Image tmpImg = new Image();
tmpImg.Source = bmpImg;

// this is required by WriteableBitmap 
tmpImg.Measure(new Size(100, 100));
tmpImg.Arrange(new Rect(0, 0, 100, 100));

// prepare scaling to 100x100
ScaleTransform scaleTrans = new ScaleTransform();
double scale = (double)100 / (double)Math.Max(bmpImg.PixelHeight, bmpImg.PixelWidth);
scaleTrans.CenterX = 0;
scaleTrans.CenterY = 0;
scaleTrans.ScaleX = scale;
scaleTrans.ScaleY = scale;

// render
WriteableBitmap writeableBitmap = new WriteableBitmap(100, 100);
writeableBitmap.Render(tmpImg, scaleTrans);
writeableBitmap.Invalidate();

// final image
Image img = new Image();
img.Source = writeableBitmap;

我希望我没有漏掉任何愚蠢的东西,但是它看起来对我来说是可以的,并且做了正确的事情(除了内存问题)。请记住,代码质量并不应该是生产质量;它只是一个快速而肮脏的原型。

我注意到我不是唯一的人;我发现与Silverlight中的图像处理相关的问题。我也意识到我可以使用一些第三方库,在服务器上进行处理或编写自己的东西,但我很惊讶Silverlight没有提供任何基本的图像处理功能。考虑到Silverlight的定位,这似乎并不是一个罕见的需求。


1
一般来说,人们现在使用像http://code.google.com/p/fjcore/上的FJCore代码库来填补这个空白。关于Silverlight的观点并不相关于问题。 - Jeff Wilcox
2个回答

4

你是否看过WriteableBitmapEx项目?这是一个开源项目,提供了大量的扩展方法来操作WriteableBitmap类。以下是如何调整大小的示例:

BitmapImage image = new BitmapImage();
image.SetSource(dialog.File.OpenRead());

WriteableBitmap bitmap = new WriteableBitmap(image);
WriteableBitmap resizedBitmap = bitmap.Resize(500, 500, WriteableBitmapExtensions.Interpolation.Bilinear);

// For uploading
byte[] data = resizedBitmap.ToByteArray();

1

我不太清楚具体情况,但如果您正在泄漏资源,您可能需要查看哪些对象实现了IDisposable接口。我猜测Stream和Image类实现了这个接口。如果是这样的话,在它们上面调用Dispose()(或者将它们的使用包装在“Using”语句中)将会立即释放它们的资源,而不是等待垃圾回收器最终启动。


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