# 关于计算机展示图像的一些问题

**一， 计算机如何存储图片的？**

比如我们在电脑显示器上面看到一张图片，是一只小狗🐶，那么它又是怎么被存储在我们的计算机内部的呢？ 在计算机里面 只有0和1两种状态，这是因为我们计算机由电路硬件晶体管来组成的，晶体管这种半导体只有两种状态，所以我们在计算机上面看到的一切都是最终由0和1组成，听起来是不是有点奇妙？

那么小狗的图片是如何变成0和1的呢？ 首先小狗的图片在屏幕上展示是由屏幕上的每一块像素点组成的。 如果你拿个放大镜对着你的图片看，你的屏幕的像素点会很清晰，一个像素块一个像素块。 那么我们可以得出一个初步结论： **图片是由像素块拼接成的。**

那么问题就转嫁到像素块上了，像素块和01有什么关系？我们知道我们现在看到的任何颜色都可以使用三原色进行混合组成，RGB(红绿蓝)，那么我们的像素块也是，它在屏幕上可以显示某一种颜色完事是因为显示器通过三原色进行按照比例混合组成了这个像素块的颜色，那么我们又可以进一步得出一个结论：**像素块的颜色是由屏幕红绿蓝的色素块混合组成的。**

那么问题再一次转嫁到红绿蓝三元色上面了，三原色和01有什么关系？这个就比较直接明了，首先我要表示一种颜色需要三原色的混合，比如我们把红色分为从0～255共256种亮度的红，蓝和绿同理，那么我们就能组合成 256\*256\*256 = 16,777,216种颜色，那么256是我们人类使用的十进制数字，我们只需要将它转换成二进制01这种计算机可以理解的二进制就可以了。于是我们就可以得到一个最终结论： **图片由像素块组成，像素块由三原色RGB组成，RGB又由十进制数字表示，十进制数字又可以转换成二进制01来表示。**

所以我们就清楚了，计算机上面的图片是如何被解释成01在计算机种存储的。

**二，屏幕分辨率和PPI**

屏幕分辨率：例如，屏幕分辨率是1024×768，也就是说设备屏幕的水平方向上有1024个像素点，垂直方向上有768个像素点。像素的大小是没有固定长度的，不同设备上一个单位像素色块的大小是不一样的。尺寸面积大小相同的两块屏幕，分辨率大小可以是不一样的，分辨率高的屏幕上面像素点（色块）就多，所以屏幕内可以展示的画面就更细致，单个色块面积更小。而分辨率低的屏幕上像素点（色块）更少，单个像素面积更大，可以显示的画面就没那么细致。

PPI：Pixels per inch 也称屏幕密度，对象线为一英寸的区域有多少个像素块。

这里需要注意的是，我们来表达屏幕够不够细致，肯定希望像素块越密集越好，所以我们应该去查看它的PPI，因为分辨率是一共用多少个像素块去表现，比如800\*600在大屏幕的电脑上，就会明显感觉画面质量锯齿严重等。 但是在一块手表屏幕上就非常的细致。&#x20;

**三，LCD和OLED**

首先查看自己的屏幕是什么类型的显示器，比如我的Mac可以在屏幕选项里面看见你的屏幕是什么类型的显示屏，我的Mac就是LCD类型的显示屏。 但是我的iPhoneX就是OLED显示屏

简单的来讲，在我们屏幕上每个像素点都是又三原色红绿蓝组成的，LCD上面的这个像素点是由背光灯(白光)，前面挡着三原色的镜头，然后通过中间夹着的偏光膜让像素展示各种颜色，而OLED没有背光灯，而是红绿蓝三原色的镜头自发光，也不用什么偏振膜来调节颜色。通过这样的方式来让像素点展示不同的颜色。

LCD有一个常见的缺陷，就是黑色并不能纯黑，它的黑色你看上去仿佛还是有一点偏白。而OLED这点就比它好，它的黑是纯黑。

当然OLED也有劣势，比如烧屏等。

具体可以查看这片帖子很容易理解: <https://www.zhihu.com/question/22263252>

**四，屏幕刷新率和FPS**

屏幕刷新率和FPS是两个事物，但是他们之间是有关系的。&#x20;

屏幕刷新率：你的显示器刷新的频率，目前一般都是60hz，也就是一秒60次，如果不是变频的显示器，变频显示器就是可以动态改变刷新频率，而不是每隔1/60秒就刷新一次。

FPS：每秒显示帧数 或者 每秒显示张数 - [影格率](https://zh.wikipedia.org/wiki/%E5%B8%A7%E7%8E%87)测量单位（frames per second），比如 你经常可以看到游戏右上角或者其他地方有 fps：70或200或300，它是每一秒显卡能给多少张画面来展示。

这里说明的是，比如我FPS：300，一秒让显卡出300幅画面，但是屏幕刷新率就是60hz，一秒我就展示60张画面，多余的画面就被自动丢弃了。&#x20;

那么会有这么想，如果是这样的话我还提高我的FPS干嘛，就60就好了和屏幕刷新率对应上。当然理想情况下，确实可以，每一帧都对应上。 但是现实并不是这样的。我们可以这么理解，屏幕的刷新率60hz每秒60次可以不受任何影响，就是每隔1/60秒就刷新一次，但是显卡并不能像屏幕一样每隔固定的1/60秒就可以输出一张图片，我举个例子：

先提 CRT 显示器原理，CRT 的电子枪按照从屏幕上面到屏幕下面扫描的方式，从上到下一行行扫描，扫描完成后显示器就呈现一帧画面，随后电子枪回到初始位置继续下一次扫描。为了把显示器的显示过程和系统的视频控制器进行同步，显示器（或者其他硬件）会用硬件时钟产生一系列的定时信号。当电子枪换到新的一行，准备进行扫描时，显示器会发出一个水平同步信号（horizonal synchronization），简称 HSync；

而当一帧画面绘制完成后，电子枪回复到原位，准备画下一帧前，显示器会发出一个垂直同步信号（vertical synchronization），简称 VSync。显示器通常以固定频率进行刷新，这个刷新率就是 VSync 信号产生的频率。尽管现在的设备大都是液晶显示屏了，但原理仍然没有变。

![](https://964606286-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M114Zqgo1V0DJ4FaGQa%2F-M7aCemecRDCn0wk6ygf%2F-M7aD_Jhpv51wXQTdeV7%2Fimage.png?alt=media\&token=bd427329-d330-4f15-b223-f6f75ea67c90)

![](https://964606286-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M114Zqgo1V0DJ4FaGQa%2F-M7_mriShe8_3_HN8lFs%2F-M7_sxURmRiX7OhO8XUN%2Fimage.png?alt=media\&token=62ed68b0-05c0-4f57-8e32-cf86187001cd)

0～1/60 秒：显卡输出一张图像A，显示器现实图像A

1/60秒～2/60秒：这一张图像特别耗费CPU导致CPU处理时间长了，当显示器要展示图片的时候，发现显卡没给新图像，那么还是显示图像A。

2/60秒～3/60秒：这一张图像一切正常，显卡在显示器刷新之前绘制出了一张新的图像C，那么显示器就刷新显示图像C

这里可以看出，图像B被丢掉了，这也就是所谓的掉帧，这也就是为什么理想情况下我们认为60FPS就可以了，但是实际上却有一些误差。 假如我们有300FPS，那么在1/60～2/60之间，显卡理论上就会多为我们输出很多张图像，这些图像的差别很小，所以即使丢帧了，在视觉上也很难察觉出来。&#x20;

但是你本来FPS就少，比如FPS：45，如果一切顺利，那么视觉上也还凑合，但是如果这里再发生掉帧，那么人眼就很容易发现，也就是我们所说卡顿。&#x20;

这里还有一点，我们会发现比如在不同的游戏里面，它的FPS不是总是恒定300或者60，是根据你游戏图像的复杂程度，CPU和GPU处理最终交给显示卡的图像频率来决定的。比如你玩一个拳皇这种游戏本来图像就很简单，显卡可以无压力的给出300FPS，但是你玩高质量的3D游戏，比如魔兽世界这种，你的显卡就很难再无压力的给出300FPS，可能只有100FPS，因为每一帧的图像绘制和渲染难度加大，需要CPU和GPU更多时间，自然在单位时间内输出的图像就少了。

垂直同步：再说下垂直同步是什么，为什么要开垂直同步，说它之前，我们需要知道我们显示器刷新是从屏幕上到屏幕下扫描显示的，就好比一个一卷画作，从上自然垂下展开一样，屏幕刷新也是这样，那么我们屏幕刷新本来就很简单，就是有一个buffer存储，里面有什么我就画什么。 但是会遇到一个这样的问题，GPU渲染完成后，不管当前显示器是否正刷新这幅画面，直接就将buffer里面的数据进行了替换，这导致了屏幕已经刷新到一半了，正在读取下一半的数据进行刷新，突然buffer数据变了，自然屏幕展示出来的图像也变了。 这会导致屏幕上一半展示和下一半展示不一致，这也就是常说的画面撕裂。 那么GPU也有解决办法就是垂直同步，就是我等等呗屏幕没刷新完我就等会再给数据呗，这样不就没撕裂了。&#x20;

例如我们iOS设备默认就是开启垂直同步的，所以如果中间有一帧图像输出比较慢，过了屏幕刷新时间，那么屏幕就还是显示上一帧的图像。会出现导致卡顿的现象。所以如果想要提高你的FPS，尽可能频率快的输出图像，那么你就要会尝试减少CPU和GPU的执行时间来解决这个问题。

**五，UIImage 解码**

我们知道在iOS当中，UIImage默认是在主线程 main thread 进行解码的。 比如从 png，jpg 解码成位图bitmap格式，bitmap格式图片其实里面就是包含54字节头部信息，标记着图片的大小等。 剩下的就是图片的内容了，用RGBA的二进制来进行表示，最终以16进制来展示。 那么我们的UIImage就是需要将png/jpg这种图片进行decode成bitmap然后拿给计算机去展示。 那么在这个decode过程中，当图片越大，色彩越丰富细致的时候，其decode就越耗时，如果这个耗时比较长，那么就会出现肉眼可见的卡顿。 因为在主线程上面执行，从原理上就是显卡一直没有接到新的图像，一直就是之前的图像，所以屏幕刷新的图像也一直是之前的图像，就造成的卡顿的效果。 那么UIImage是lazy的，也就是你不用它，它并不会解码，常见的办法是在后台线程进行CGContextDrawImage进行强行解码，再返回主线程赋值来展示。&#x20;

补充 新款iPad Pro：

120hz是触控采样率，就是跟手的能力，并不是所谓的屏幕刷新率。 在手持设备界并不是很常提屏幕刷新率， iPad Pro上了一个120hz的屏幕刷新率，然后文案写了出来，主要是为了配合Apple pencil的使用和增强体验 其他大部分产品还是60hz的屏幕刷新率
