在线程池线程上调整Windows Phone 7上的图像大小?

19

我正在编写一个 Windows Phone 7 应用程序,处理大量的图片资源 - 这些图片可以从几百个像素到 1080P(未来可能更高)。

由于图片非常消耗资源,因此我选择了在手机上缓存和调整大小,然后再显示图片。

这意味着,在用户输入图像存储的 IP 地址后,第一次设置时,我可以要求他们等待几分钟,直到所有内容都被检索/调整大小/缓存。从那时起,他们就可以拥有良好而顺畅的性能。

目前,我的缓存管理器通过 Uri 和文件位置的字典跟踪图像。我有一个队列,每次处理最多 5 张图片(异步网络请求,调整大小在线程池线程上半完成)。

我遇到的问题是 Silverlight 中的 WritableBitmap 类是一个 UI 元素,这意味着我必须通过 Dispatcher 转换到 UI 线程来进行实际的调整大小操作,这很愚蠢并且会降低整个过程的速度 - 这也意味着我的缓存管理器实际上是单线程。

所以 它的执行顺序是 缓存管理器(线程池)- >异步网络请求(线程池)- >回调(线程池)- >调整大小(UI 线程)- >标记缓存作业已完成(线程池)。

我一直在寻找第三方库,它可以 A) 编译并在 Windows Phone 7 上运行,B) 能够通过操作流或字节数组来调整各种格式的图像而不依赖于 UI 线程。

有人对此有任何经验吗?

谢谢,

Tyler


有没有可能在下载图片时使用 Web 服务来调整图片大小? - Damian
它们来自我无法控制的外部系统 =/ - Tyler
你可以将Url传递给一个Web服务,该服务将执行下载+调整大小操作,然后将较小的图像传回Windows手机?我想这就是Damian所说的。 - Vincent Vancalbergh
我已经回答了一个关于使用Web服务的问题,并提出了一些建议。但是,我不确定我完全理解你的问题... 我可以请你澄清几个问题吗?1)每个图像您想要输出多少种不同的尺寸?2)我猜不是,但是您能否只在手机上使用MediaLibrary?这将为您提供免费的缩略图。3)您实际上已经对处理进行了分析吗?根据您所说的,调整大小实际上是一个问题,这在移动情况下,我会预计图像下载实际上是您的瓶颈。 - Stuart
我现在已经达到了100%的性能并且非常满意,但是当用户第一次输入Xbox Media Center的IP地址时,我会强制让他们等待,直到我运行完初始缓存作业。根据他们的库的大小,我可以看到这项工作接近10分钟(我的库有300部电影和20多个电视季,大约需要1分钟)。因此,我真的希望尽可能加快缓存速度。 - Tyler
显示剩余5条评论
7个回答

3
为了减小下载大小并减轻手机CPU的处理负担,我会将这项工作推向网络服务。例如,您可以在某个在线位置托管像开源WebImageResizer代码这样的服务http://webimageresizer.codeplex.com/ - 例如,在免费的AppHarbor服务器上。或者您可以使用商业(免费)服务,如:两者都能让您在具有超快速连接的服务器上快速处理图像,并通过其有限的数据连接向手机传递较小的图像。

很抱歉,这对我的应用程序来说不可行。该应用程序是Xbox Media Center遥控器,旨在通过Wifi使用(可以通过3G等使用,但没有太大意义)。我真的不想强迫人们将其媒体库图像上传到Web服务,然后再返回到他们的手机上使用我的应用程序。我也不想要求他们必须有互联网连接才能使用我的应用程序。 - Tyler
谢谢解释。现在我明白你在说什么了...我认为将其从UI线程中移除不会有任何改进。您可能可以通过找到更快的调整大小算法来加快速度,但是您问题中的“单线程”措辞并不是问题的根本 - 基本上您使用的是一台只有一个CPU和一个核心(以及一些来自UI的图形处理)的手机。 - Stuart
1
我能想到让这个过程更快的方法有以下几种:1)在缓存期间向用户显示一些反馈信息;2)让用户在缓存完成之前开始使用应用程序(使用placekitten缩略图);3)再次查看媒体中心API - 是否有任何方法可以请求缩略图?4)除了调整大小,还要查看图像解码库,以查看下载的图像是否已经包含缩略图(例如,JPEG通常在JFIF流中嵌入缩略图)。提前道歉 - 因为我猜测您已经尝试了所有这些方法! - Stuart
  1. 用户目前会看到一个屏幕,解释为什么需要缓存,并显示还有多少图片需要缓存 - 我认为如果我解释一下原因,他们就不会那么介意了。
  2. 在缓存完成之前,我不能让他们使用应用程序,因为当图像被缓存/调整大小时,调整大小是在UI线程上完成的(请参阅第一篇帖子),所以他们会遇到不可接受的UI卡顿,而不知道原因。
  3. 没办法向Xbox Media Center请求更小的图像,最后
  4. 这不是一个坏主意,我会去研究一下 :). 缓存屏幕截图在这里:http://imgup.co.nz/1751
- Tyler
很酷 :) 在1)如果您每隔几秒钟显示一张新图片,那么他们可能会更喜欢这条消息。在2)查看您的屏幕截图时,我认为可以进行按需图像处理,而不是预先下载...但从根本上讲,这都是您的选择。无论您决定什么,祝你好运! - Stuart

0

Tyler - 你提到在初始启动时,应用程序会从一个IP地址(我猜是互联网上的)检索图像?

这意味着在用户输入图像存储的IP地址后的第一次设置中,我可以要求他们等待几分钟,直到所有图像被检索/调整大小/缓存。从那时起,他们就可以享受良好且迅捷的性能。

如果是这样的话,我认为一些答案所建议的创建代理的方法实际上是可行的解决方案。我会将其结构化如下:

您的应用程序 -> 代理处理程序的Web请求

string imageUrl = HttpUtility.UrlEncode("http://[user's_ip]/path_to_image.png");
http://domain.com/your_proxy.ashx?users_image_url=imageUrl 

后端代理处理程序应该请求图像,对其进行调整大小,并将调整大小后的图像返回到您的应用程序。

您的应用程序 -> 缓存返回的调整大小的图像

根据需要循环...

更新:

事实证明,除了使用本机的 WriteableBitmap 类之外,还有一种方法可以在 WP7 上调整图像大小。有一个名为 .SaveJpeg() 的方法允许这样做,我们目前正在我们的 WP7 应用程序 CitySourced 中使用它。您的代码应该类似于:

wb.SaveJpeg(stream, width, height, orientation, quality);

唯一的遗憾是它只能通过编写 .JPG 文件来工作,没有 .PNG 支持。如果这对您的用例有用,请告诉我。

顺便说一下,我认为服务器能够比设备更快地调整图像大小,因此这可能比让设备处理调整大小更快的解决方案。此外,调整大小后的图像将比下载原始的大尺寸图像更快地到达设备。 - Jason
不错的尝试,但您没有读完其他评论,是吗?:p 我的应用程序在家庭网络上使用wifi。我不想建立对互联网的需求。 - Tyler
你可以构建处理程序以在内部网站上运行(通过私有IP地址或主机文件修改可访问),它将与公共处理程序一样工作。 - Jason

0

仍然依赖于WriteableBitmap,它是一个UI元素,所以根本没有回答我的问题。 - Tyler
实际上,WriteableBitmap的SaveJpeg方法可以在UI线程之外调用。 - henon

0

ImageTools库既支持WP7,也支持图像调整大小,所以使用它可能会更成功。


ImageTools在WP7上不支持PNG格式,也没有提供任何我能找到的调整大小的工具(它们提供了一个接口但没有实现)。 - Tyler
如果您查看源代码控制中的最新版本(在CodePlex上),现在它在WP7上有一个PNG实现。调整大小功能在ExtendedImage_Operations类文件中作为ExtendedImage类上的静态Resize方法提供。 - Derek Lakin
不幸的是,Resize方法需要一个IImageResizer接口作为参数,而我看不到任何IImageResizer的实现。 - Tyler
1
默认的 IImageResizerImageTools.Filtering.NearestNeighborResizer,它位于 ImageTools.Filtering 组件中(并且在 WP7 下也可用)。 - Derek Lakin
哎呀,这个程序到处都在抛出异常,而且运行速度慢得要死(没有文档,所以我可能做错了什么,但是当我试图将图像源设置为内存流时,它就会抛出异常)。我开始认为Silverlight WriteableBitmap类至少执行其调整大小代码是本地化的和/或硬件加速的,因为没有第三方解决方案能够接近它(即使它们正在自己的线程上运行)。 - Tyler

0

您想在服务器上显示文件吗?

如果是的话,我认为您选择了错误的解决方案。将大型图像传输,然后调整大小是毫无意义的。我建议在服务器上保留它们的低分辨率和高分辨率版本。

如果不是的话,我无法帮助您。我找到了this article,但我认为您已经看过了。


0

我认为你的问题不是性能,而是你如何显示图像。我认为最好始终显示默认缩略图,然后在后台作业调整大小后更新缩略图。这样应用程序就可以更快地使用。


-1

不提及WP7支持,不是免费的,你似乎没有任何个人经验,所以我猜你不能评论速度等方面。 - Tyler

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