在UIImageView中显示隔行扫描(逐行扫描)图像

时间:2013-12-15 15:16:23

标签: ios iphone objective-c cocoa-touch uiimageview

我试图在下载时显示JPEG图像,使用部分数据,类似于许多网络浏览器或facebook应用程序。

图像质量低(只是部分数据),然后以完整质量显示完整图像。

最好显示在VIDEO HERE

我遵循了这个问题:

How do I display a progressive JPEG in an UIImageView while it is being downloaded?

但我得到的只是一个imageview,当数据保持进入时呈现,没有低质量版本,没有真正的渐进式下载和渲染。

任何人都可以共享代码段或指向我可以找到有关如何在iOS应用中实现此功能的更多信息吗?

尝试此链接,例如显示JPEG信息,它将图像标识为渐进式

http://www.webpagetest.org/jpeginfo/jpeginfo.php?url=http://cetus.sakura.ne.jp/softlab/software/spibench/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 PROJECT HERE

5 个答案:

答案 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,具体取决于首先到达的图像。结果非常顺利。

这是gist showing the basic idea

这可能不适合您,因为您可能无法控制进程的服务器端。在我实现这个之前,我正在寻求David H所描述的解决方案。一旦我意识到我还需要自己访问低分辨率图像,这本来就会有很多工作,而且效果不大。

here

解释了另一种可能更符合您要求的方法

这已演变为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

另见this blog entry

为了简化您的生活,您只需要项目中的这些文件:

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版本。