视觉-iOS中图片文件渲染到屏幕的过程

一、图片到屏幕view过程

1、数据处理过程


图片数据
  • 1)将原始图片数据(png/jpg等)加载到内存中
  • 2)CPU解压图片数据
  • 3)渲染图片数据渲染到屏幕上

2、硬件协同处理细节

硬件处理
  • 1)CPU:计算视图frame,图片解码,需要绘制纹理图片通过数据总线交给GPU
  • 2)GPU: 纹理混合,顶点变换与计算,像素点的填充计算,渲染到帧缓冲区
  • 3)时钟信号:垂直同步信号V-Sync / 水平同步信号H-Sync
  • 4)iOS设备双缓冲机制:显示系统通常会引入两个帧缓冲区,双缓冲机制

二、图片加载到渲染的工作流程

1、从文件加载图片数据 可以使用类方法+imageNamed: ,此时我们得到图片原始数据
2、将UIImage 赋值给UIImageView
3、CATransaction捕获到UIImageView图层树的变化
4、主线程runloop提交 CATransaction,开始进行解码和图像渲染,这里会涉及到

  • 如果图像数据为未解码的PNG/JPG,解码为位图数据
  • GPU处理数据需要字节对齐,Core Animation会拷贝一份数据,进行字节对齐
  • GPU处理位图数据,进行渲染

5、渲染

  • GPU获取获取图片的坐标
  • 将坐标交给顶点着色器(顶点计算)
  • 将图片光栅化(获取图片对应屏幕上的像素点)
  • 片元着色器计算(计算每个像素点的最终显示的颜色值)
  • 从帧缓存区中渲染到屏幕上

注意:
1、图片只有在确认需要显示时,CPU才对其进行解压;+imageName:or+imageNamed:inBundle:compatibleWithTraitCollection:加载的图片,系统会对其自动缓存,以便下次使用,但如果用+imageWithContentsOfFile:-initWithContentsOfFile:系统会每次都从disk加载,对应的都需要解压;imageWithData直接读取原始数据,如果非GPU能直接处理的数据(位图或矢量图)是需要解压的;
2、解码是一个比较消耗CPU的操作,且默认在主线程,当界面上一次性确定显示多张图片时表现得尤为突出,此时一般的做法可以将解码操作放到异步线程去完成,解码后再用来展示

三、探究YYImage

1、YYImage 类结构分析

  • 图像层:YYImage, YYFrameImage, YYSpriteSheetImage
  • 视图层:YYAnimatedImageView
  • 编/解码层:YYImageCoder

2、分析YYAnimatedImageView

  • 初始化
- (instancetype)init {
    self = [super init];
    _runloopMode = NSRunLoopCommonModes;
    _autoPlayAnimatedImage = YES;
    return self;
}

- (instancetype)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    _runloopMode = NSRunLoopCommonModes;
    _autoPlayAnimatedImage = YES;
    return self;
}

- (instancetype)initWithImage:(UIImage *)image {
    self = [super init];
    _runloopMode = NSRunLoopCommonModes;
    _autoPlayAnimatedImage = YES;
    self.frame = (CGRect) {CGPointZero, image.size };
    self.image = image;
    return self;
}

初始化中指定了runloopModeNSRunLoopCommonModes

  • 动画的link
  [_link addToRunLoop:[NSRunLoop mainRunLoop] forMode:_runloopMode];

_runloopMode 指定到了 CADisplayLinklink中,不断地替换_curFrame用来跟新layer里面显示的图片frame,将link的指定成NSRunLoopCommonModes保证了在拖动滚动视图时动画还能继续。

  • 图片解压 _YYAnimatedImageViewFetchOperation
//创建_requestQueue 设置最大并发量1
_requestQueue = [[NSOperationQueue alloc] init];
_requestQueue.maxConcurrentOperationCount = 1;
//解码操作加入_requestQueue
_YYAnimatedImageViewFetchOperation *operation = [_YYAnimatedImageViewFetchOperation new];
operation.view = self;
operation.nextIndex = nextIndex;
operation.curImage = image;
[_requestQueue addOperation:operation];
@implementation _YYAnimatedImageViewFetchOperation
- (void)main {
    ...
    
    for (int i = 0; i < max; i++, idx++) {
        @autoreleasepool {
            ...
            if (miss) {
                 //解码图片,并且标记
                UIImage *img = [_curImage animatedImageFrameAtIndex:idx];
                img = img.yy_imageByDecoded;
                if ([self isCancelled]) break;
                LOCK_VIEW(view->_buffer[@(idx)] = img ? img : [NSNull null]);
                view = nil;
            }
        }
    }
}
@end

可以看到,_YYAnimatedImageViewFetchOperation解码image图片的操作是通过
NSOperationQueue_requestQueue来异步来处理的

  • 图片数据buffer缓存
NSMutableDictionary *_buffer; ///< frame buffer

这里cache了显示所需要解压好的图片buffer数据,以便重复使用; 当然这里还有缓存限制和memory告警时清理缓存的机制,我这里就不一一赘述了

参考链接:
https://developer.apple.com/documentation/uikit/uiimage
https://www.jianshu.com/p/72dd074728d8
https://developer.apple.com/documentation/uikit/uiimage

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,240评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,328评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,182评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,121评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,135评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,093评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,013评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,854评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,295评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,513评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,678评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,398评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,989评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,636评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,801评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,657评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,558评论 2 352