Image and Graphics Best Practices

目录:

一、UIImage and UIImageView
二、Image Scource
三、Custom drawing with UIKit
四、Advanced CPU and GPU techniques
五、总结

一、UIImage and UIImageView

问题1:UIImageVIew显示图片,会有哪此过程?(加载——解码——渲染)
Image and Graphics Best Practices_第1张图片
显示图片的过程
  • 1.加载一个图片,产生一个的DataBuffer(存储了二进制的元数据)
    2.将图片解码,解码过程中会产生一个ImageBuffer(记录每一个象素的色彩信息)
    3.渲染一个图片,渲染的过程中会产生一个FrameBuffer(存储了App的每帧的实际渲染输出)

问题2 :内存,cpu,电池寿命,响应速度的关系?
Image and Graphics Best Practices_第2张图片
各资源间的关系
  • 内存占用高,引起CPU占用高,导致耗电快,响应速度慢

问题3:我们在显示图片时,解码操作会消耗较高的内存,我们在这个过程中,如何节约内存?
  • 1.降低采样:减少ImageBuffer的size,从而降低内存的占用
func downsample(imageAt imageURL: URL, to pointSize: CGSize, scale: CGFloat) -> UIImage {
    let imageSourceOptions = [kCGImageSourceShouldCache: false] as CFDictionary
    let imageSource = CGImageSourceCreateWithURL(imageURL as CFURL, imageSourceOptions)!
    let maxDimensionInPixels = max(pointSize.width, pointSize.height) * scale
    let downsampleOptions = 
       [kCGImageSourceCreateThumbnailFromImageAlways: true,
         kCGImageSourceShouldCacheImmediately: true,
         kCGImageSourceCreateThumbnailWithTransform: true,
         kCGImageSourceThumbnailMaxPixelSize: maxDimensionInPixels] as  CFDictionary
    let downsampledImage =
        CGImageSourceCreateThumbnailAtIndex(imageSource, 0, downsampleOptions)!
    return UIImage(cgImage: downsampledImage)
}

2.预取和异步解码:由于当用户快速滑动的时候,会频繁在主线程中进行图片的解码操作,会造成cpu某一时刻的占用率极高。为了使cpu资源的平滑分配,使用预取(prefetchRowsAt:)和异步解码(通过多线程,在子线程获取解码后的图片,然后展示到主线程上,降低 CPU 的占用)。

let serialQueue = DispatchQueue(label: "Decode queue")
  func collectionView(_ collectionView: UICollectionView,
                     prefetchItemsAt indexPaths: [IndexPath]) {
     // Asynchronously decode and downsample every image we are about to show
    for indexPath in indexPaths {
         serialQueue.async {
           let downsampledImage = downsample(images[indexPath.row])
           DispatchQueue.main.async { self.update(at: indexPath, with: downsampledImage) }
         }
     }
 } 


二、Image Scource

问题1:图片从哪里来?

1.在assetCatelog中的图片资源
2.在应用或框架中的bundle文件
3.在文件系统中的文件
4.从�网络上下载的文件

问题2:为什么推荐ImageAssets

1.基于名称和特征的优化查找
2.智能缓冲缓存
3.应用瘦身(应用在安装时,根据设备选择资源)
4.矢量化图片(勾选Preserve Vector Data选项)
注:如果有一个图片有多张尺寸,最好用多个图片资源代替,而不选择矢量栅格化


三、Custom drawing with UIKit

问题1:继承View的子类实现draw方法和使用UIImageView显示一个图片,会有哪些不同?
Image and Graphics Best Practices_第3张图片
添加多个view和继承view对比

1.继承View的子类:继承UIView重写draw方法,CALayer会创建一个备用缓存,然后再将内容传给FrameBuffer。
2.UIImageView:ImageView创建图片,并让图片创建一个解码后的图片缓存,而且将解码后的图片给CALayer,作为它的内容

问题2:如何减少备用缓存

1.设置ContentsFormat属性同时更新layerWillDraw的实现,来隐式的开启优化(设置CALayer的属性来提示是否需要更广的色域)
2.通过属性的方法,减少draw方法的重写从而减少后备缓存的使用。比如UIView.backgroundColor渲染frameBuffer时不需要后备缓存(不推荐使用图案色填充,可用UIImageView的tiling Image代替)
3.圆角时,使用CALayer的cornerRadius或者修剪好的图片(UIView的maskView和CALayer.maskLayer会有临时图片缓存,而CALayer的cornerRadius则没有)
4.使用UIImageView和IULabel
注:屏幕之外,使用UIGraphicsImageRenderer更有效率。


四、Advanced CPU and GPU techniques

1.对图片进行实时处理时考虑使用CoreImage,它解放了CPU,在GPU上执行。 `[[UIImage alloc] initWithCIImage:]
2.使用CVPixelBuffer在Metal,Vision,Accelerate框架之间传递数据


五、总结:

1.预取和异步解码的实现
2.使用UIImageView 和 UILabel来减少Backing Store
3.不要无意中关闭了自定义draw方法中系统尝试做的优化
4.推荐使用 Image Assets
5.避免过度依赖Preserve Vector Data

你可能感兴趣的:(Image and Graphics Best Practices)