如何制作具有快速显示的大图像的 UIScrollView(如 Photos.app)?

发布于 2024-10-12 07:56:33 字数 486 浏览 6 评论 0原文

我正在尝试制作一个简单的图像查看器来查看 ALAssetRepresentation 的全分辨率图像。事实证明事情并没有那么简单。

我的第一个方法是在 UIScrollView 中创建一个大的 UIImageView。虽然这确实有效,但速度非常慢。

使用“照片”应用程序时,当您触摸图像时,会立即打开较大的版本。首先,绘制的是分辨率非常低的图像。但很快,一张更高分辨率的图像出现了。另外,如果我放大,图像首先会降低分辨率,然后分辨率会增加。

我查看了 WWDC 2010 主题演讲 #104,其中描述了 Photos.app 的工作原理。但我该如何实施呢?在主题演讲中,演示使用了预平铺图像,这是我无法从 ALAssetRepresentation 中获得的东西。我尝试过加载全分辨率版本并使用 CATiledLayer 进行绘制,虽然缩放等速度并不慢,但绘制图块时却太慢了。

Photos.app 是否在某处缓存了所有图像的较低分辨率版本,或者发生了什么?关于该怎么做的一些指示会很有帮助。

I'm trying to make a simple image viewer for viewing the full resolution image of an ALAssetRepresentation. It turns out it's not quite that simple.

My first approach was to just make a big UIImageView inside the UIScrollView. While this did work, it was very slow.

When using the Photos app, when you touch an image, the larger version opens instantly. At first, there's a very low resolution image being drawn. But shortly, a higher resolution image appears. Also, if I zoom in, the image is first lower resolution and then the resolution increases.

I checked out the WWDC 2010 keynote #104 where it is described how Photos.app works. But how am I supposed to implement this? In the keynote, the demo uses pre-tiled images, something which I cannot get from an ALAssetRepresentation just like that. I've tried just loading the full resolution version and just drawing it using CATiledLayer and while it's not slow for zooming et.c, it's way too slow when drawing the tiles.

Is Photos.app caching a lower resolution version of all images somewhere or what's going on? Some pointers on what to do would be helpful.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

半边脸i 2024-10-19 07:56:33

是的,Photos.app 正在缓存较低分辨率的图像。好消息是您也可以获取这些缓存版本。您可能已经了解 ALAssetRepresentation 的 fullScreenImage 属性和 ALAsset 的缩略图属性。这些应该加载得更快。

我发现高分辨率图像仅加载可能需要 1-2 秒,因此我猜测仅在后台加载高分辨率图像可能会为您带来帮助。

那么,如何加载低分辨率版本的图像,然后在有 i 时切换到高分辨率版本呢?它可能有点复杂,但希望这可以帮助您入门。由于您使用的是 AssetsLibrary,因此您将必须使用 iOS 4,这是个好消息,因为您可以使用块和 GCD/libdispatch 相当轻松地完成此操作。我很高兴您正在观看 WWDC 视频 - 请查看第 206 和 211 场会议,了解有关 GCD 的大量重要信息。

基本思想是,您将在主线程上显示较低分辨率的版本,然后要求后台线程加载全分辨率图像,然后告诉 CATiledLayer 切换到全分辨率图像。

- (void)displayAsset:(ALAssetRepresentation *)asset {
  UIImage *lowresImage = [UIImage imageWithCGImage:asset.fullScreenImage
                               orientation:asset.orientation scale:asset.scale];
  // Add code here to display the lowresImage

  dispatch_async( dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
    ^ {
      // Load the full resolution image from the asset
      UIImage *highresImage = [UIImage imageWithCGImage:asset.fullResolutionImage
                                   orientation:asset.orientation
                                   scale:asset.scale];

      // Once done, tell the main thread to display the tiles
      dispatch_async( dispatch_get_main_queue(),
        ^ {
          // Code to swap out the lowresImage for highresImage
        });
    });

}

Yes, Photos.app is caching lower resolutions images. The good news is that you can get at those cached versions too. You're probably already aware of the fullScreenImage property of ALAssetRepresentation and the thumbnail property of ALAsset. Those should be much quicker to load.

What I've found with high resolution images is that just loading it can take 1-2 seconds, so I'm guessing that just doing the loading of the high res image in the background might do the trick for you.

So, how to load the low-res version of the image and then switch to the high-res version when you have i?. It can be a bit complicated, but hopefully this should get you started. Since you're using AssetsLibrary, you're going to have to use iOS 4, which is good news because you can do this fairly easily with blocks and GCD/libdispatch. I'm glad you're watching the WWDC videos--check out sessions 206 and 211 for lots of great info on GCD.

The basic idea is this that you're going to display the lower resolution version on the main thread, then ask a background thread to load the full resolution image, then tell the CATiledLayer to switch to the full resolution image.

- (void)displayAsset:(ALAssetRepresentation *)asset {
  UIImage *lowresImage = [UIImage imageWithCGImage:asset.fullScreenImage
                               orientation:asset.orientation scale:asset.scale];
  // Add code here to display the lowresImage

  dispatch_async( dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
    ^ {
      // Load the full resolution image from the asset
      UIImage *highresImage = [UIImage imageWithCGImage:asset.fullResolutionImage
                                   orientation:asset.orientation
                                   scale:asset.scale];

      // Once done, tell the main thread to display the tiles
      dispatch_async( dispatch_get_main_queue(),
        ^ {
          // Code to swap out the lowresImage for highresImage
        });
    });

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文