iOS图像加载原理

图片加载

在iOS中,图片显示的过程大致如下:

  1. 从磁盘读取图片并加载到内存。(data buffer)
  2. CPU对图片进行解码,获取图片原始数据。(image buffer)
  3. 渲染图片,生成frame buffer,显示硬件会从frame buffer中读取,显示到屏幕上。
iOS图像加载原理_第1张图片
image.png
iOS图像加载原理_第2张图片
image.png

在这个过程中,UIImage类似于modal,负责加载图片,UIImageView类似于View,负责渲染和展示图片。

缓冲区

Buffers:一段连续的内存区域。
Image buffers:表示图像在内存中的信息,每个元素表示图片每个像素的颜色和透明度。
data buffers:描述图片元数据。描述存储的图片的大小,格式等信息。
Frame buffers:保存在App中实际渲染后的输出。当App的视图层次结构发生变化时,UIKit将重新渲染App的窗口及所有子视图到frame buffers中。

Decode

UIImage在加载图片数据后,需要分配一个image buffer,用来存储decode后的图片信息。这个image buffer的大小目前和data buffer一样,然后执行解压操作,解压后image buffer会变大,大小原始图片的size有关,和原始图片的内存占用无关。


iOS图像加载原理_第3张图片
image.png

解压完成后,当图像重新进行渲染时,UIImageView会对image buffer中的数据进行复制和缩放,放到frame buffer中。

解码时的内存分配与要解码的图像的size有关,与要渲染的view的大小无关。
UIImage会持续持有image buffer,防止重复解码。

向下采样

实际开发中,要渲染的视图一般比图像实际大小要小,因此在解码之前,可以采用一种向下采样的技术,减小decode时的内存占用。


iOS图像加载原理_第4张图片
image.png

向下采样发生在decode之前,使用Core Graphic对图像进行缩略操作。

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)
}

你可能感兴趣的:(iOS图像加载原理)