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

时间:2009-08-04 22:23:26

标签: silverlight silverlight-3.0 image-processing

这是我在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定位的地方,似乎并不是一个不寻常的要求。

2 个答案:

答案 0 :(得分:4)

你看过WriteableBitmapEx project了吗?这是一个开源项目,为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 :(得分:1)

我不知道这里的具体细节,但如果你正在泄漏资源 - 你可能会看看你的哪些对象实现了IDisposable接口。我猜想Stream和Image类实现了这个接口。如果他们这样做 - 在他们身上调用Dispose()(或将他们的用法包装在“Using”语句中)将导致他们立即释放他们的资源,而不是等待垃圾收集器最终启动。