我试图在下载时显示JPEG图像,使用部分数据,类似于许多网络浏览器或facebook应用程序。
图像质量低(只是部分数据),然后以完整质量显示完整图像。
最好显示在VIDEO HERE
中我遵循了这个问题:
How do I display a progressive JPEG in an UIImageView while it is being downloaded?
但我得到的只是一个imageview,当数据保持进入时呈现,没有低质量版本,没有真正的渐进式下载和渲染。
任何人都可以共享代码段或指向我可以找到有关如何在iOS应用中实现此功能的更多信息吗?
尝试此链接,例如显示JPEG信息,它将图像标识为渐进式
我使用了正确的代码序列
-(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);
}
}
但是代码只显示加载完成时的图像,其他图像会在下载时显示,但只有从上到下,没有低质量版本,然后逐渐添加细节,如浏览器那样。
答案 0 :(得分:9)
这是我有一段时间感兴趣的主题:似乎无法使用Apple的API做任何你想要的事情,但如果你可以花时间在这上面,你可能会让它发挥作用。
首先,您需要一个JPEG解码库:libjpeg或libjpeg-turbo。然后,您需要将其集成到可以与Objective-C一起使用的内容中。有一个开源项目使用这个库PhotoScrollerNetwork,它利用turbo库在下载时“动态”解码非常大的jpegs,因此它们可以被平移和缩放(PhotoScroller是一个Apple项目它可以进行平移和缩放,但需要预先平铺的图像。)
虽然上述项目并不完全符合您的要求,但您应该能够解除大部分libjpeg-turbo接口以解码渐进式图像并在接收到时返回低质量图像。看起来您的图像非常大,否则几乎不需要渐进式图像,因此您也可以找到上述使用项目的平移/缩放功能。
PhotoScrollerNetwork的一些用户要求支持渐进式图像,但似乎在网络上几乎没有使用它们。
编辑:第二个想法:如果你的网站是用来销售渐进式图像的(并且我认为这是因为通常很少找到它),你可以采取完全不同的机制。
在这种情况下,您将构建一个自己设计的二进制文件 - 其中包含4个图像。前四个字节将提供其后的数据长度(并且每个后续图像将使用相同的4字节前缀)。然后,在iOS端,随着下载开始,一旦你获得第一个图像的完整字节,你可以使用它们来构建一个小的低分辨率UIImage,并在接收下一个图像时显示它。当下一个完全到达时,您将使用较新的较高分辨率图像更新低分辨率图像。它可能你可以使用拉链容器,并在飞行减压 - 不是100%肯定。在任何情况下,以上都是您问题的标准解决方案,并且会为libjpeg提供几乎相同的性能,而且工作量要少得多。
答案 1 :(得分:3)
我已经为我正在处理的应用程序实施了渐进式加载解决方案。它不使用渐进式Jpeg,因为我需要更多的灵活性来加载不同版本的版本,但我得到了相同的结果(并且它工作得很好,绝对值得实现)。
这是一款与服务器配合使用的相机应用程序。所以这些图像来自iPhone的相机并远程存储。当服务器获取图像时,它会被处理(使用imageMagick,但可能是任何合适的库)并存储为3种尺寸 - 小拇指(~160 x 120),大拇指(~400x300)和全尺寸(〜双视网膜)屏幕尺寸)。目标设备是视网膜iPhone。
我有一个ImageStore类,它负责从任何地方异步加载图像,首先尝试最快的位置(实时缓存,本地文件系统缓存,资产库,网络服务器)。
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
可能最终应用小拇指,然后是大拇指,最后将全分辨率图像应用于单个imageView,具体取决于首先到达的图像。结果非常顺利。
这可能不适合您,因为您可能无法控制进程的服务器端。在我实现这个之前,我正在寻求David H所描述的解决方案。一旦我意识到我还需要自己访问低分辨率图像,这本来就会有很多工作,而且效果不大。
解释了另一种可能更符合您要求的方法这已演变为NYXProgressiveImageView
,UIImageView的子类,作为NYXImagesKit的一部分分发
最后......对于一个真正的hacky解决方案,你可以使用UIWebView来显示渐进式PNG(似乎不支持渐进式JPegs)。
<强>更新强>
推荐NYXProgressiveImageView
后,我意识到这就是你一直在使用的东西。不幸的是你没有在你的原帖中提到这一点,所以我觉得我已经陷入了困境。事实上,再次阅读你的帖子,我觉得你有点不诚实。从您的帖子的文本,看起来“DEMO”是您创建的项目。事实上你没有创建它,你从这里复制它:
http://cocoaintheshell.com/2011/05/progressive-images-download-imageio/ProgressiveImageDownload.zip
伴随着来自cocoaintheshell的this blog entry 您所做的唯一更改是一个NSLog行,并更改JPG测试URL。 您发布的代码段不是您的,它是从此项目复制而没有归属。如果你在帖子中提到这一点,它会为我节省一大堆时间。
无论如何,回到帖子......当你使用这段代码时,你应该使用当前版本,这是在github上:
https://github.com/Nyx0uf/NYXImagesKit
为了简化您的生活,您只需要项目中的这些文件:
NYXProgressiveImageView.h
NYXProgressiveImageView.m
NYXImagesHelper.h
NYXImagesHelper.m
接下来,您需要确保使用GOOD图像进行测试
例如,这个PNG效果很好:
http://www.libpng.org/pub/png/img_png/pnglogo-grr.png
你还需要注意这个神秘的评论:
/// Note: Progressive JPEG are not supported see #32
JPEG tempImage渲染似乎存在一个问题,我无法解决这个问题 - 也许你可以。这就是为什么你的“Demo”无法正常工作的原因。
更新2
添加了gist
答案 2 :(得分:1)
我相信这就是你要找的东西:
https://github.com/contentful-labs/Concorde
在iOS和OS X上下载和解码渐进式JPEG的框架,它使用libjpeg-turbo作为基础JPEG实现。
答案 3 :(得分:0)
答案 4 :(得分:0)
我遇到了同样的问题,然后我发现了一些棘手的问题,但它的解决方案却不合适。但是它确实有效。
加载后必须加载低分辨率/缩略图图像然后加载 实际形象。
This is example对于android我希望你能把它变成ios版本。