闲聊js6: 创建一个演示用的渲染库4(渲染表面,像素格式,光栅化,位块传输,图形与图像)

本篇的目的是要了解:

  • canvas 像素格式

  • canvas渲染表面以及内存大小的计算

  • 光栅化

  • 位块传输

  • 图形和图像的区别

上一篇我们了解到: 当css sizeelem size 不一致的时候,会导致渲染后的效果发生形变。

css size 决定了显示区域的大小,但是实际渲染区域却是由elem size确定的!!!

计算机在渲染图形图像时,总是以像素(px)这个物理单位进行定位置,定尺寸,定效果的。

而elem size 只能以px为单位设置元素大小,因为canvas需要使用这个尺寸分配渲染表面的像素集合内存,所有的canvas后续绘图操作都是绘制到这个渲染表面上的。

所以上一篇中的文字绘制实际上是绘制到了渲染表面上去了,而不是绘制到css size规定的显示区中!

一些基础概念:

什么是像素格式(pixel format)?

像素格式就是像素色彩每个分量大小排列方式。这种格式以每个像素所使用的总位数以及用于存储像素色彩的红、绿、蓝和 alpha 分量的位数指定。这个是百度解释,太学术化了。简单说(按最常规的情况进行解释),就是:

  • 分量(component)包括: R(red)、G(green)、B(blue)、A(alpha)

  • 一个像素(pixel)可以由3个(RGB)或4个(RGBA)分量组成(一般情况下如此,但还有很多特殊像素格式并不是由3/4个分量组成)

  • 分量大小是指每个分量的bit(不是bytes)数是多少,例如我们一般都是使用每个分量为8 bit的颜色表示法(canvas2d中就是如此),R8G8B8A8, 1 pixle = 4 compent = 4 componet * 8 bits = 32 bits = 32 bits / 8 bits(1 bytes = 8 bits) = 4 bytes。也就是说R8G8B8A8(canvas2d像素格式)的话,一个像素占用4个字节的内存

  • 实际上很多3D api,例如dx/gl还有更多像素格式:R16B16G16A16 /R32G32B32A32...,每种api都支持遍历拥有的像素格式方法,可以列出一长串

  • 分量的排列方式: 不同的渲染API可能使用不同的分量排列方式,例如:canvas RGBA方式排序各个分量,而GL/DirectX可以使用ARGB,BGRA,RBGA....等排序方式

总结一下像素格式:

 像素是由哪些分量组成
 每个分量多少个bit数量(不是byte)
 分量是如何排列的

什么是渲染表面?

渲染表面就是以像素为单位表示的内存块(若分配在显存,则是显存块)。

简而言之,渲染表面(render surface)就是内存图像,所有的绘制操作最后都以像素色彩方式填充到这个内存图像中

具有两个必须的特性:

  • size(width/height)
  • 像素格式(RGB,RGBA,R8G8B8A8,R32G32B32A32,....,......,n多种)

有了上面两个特性,就能确定内存块的大小了,计算公式很简单:
RGBA RenderSurface memory bytes = width * height * 4bytes

所以elem size 以及canvas2d raga像素格式确定了canvas2d渲染表面的内存大小

有了渲染表面,就可以直接操作像素进行颜色获取或设置。

什么是光栅化:

光栅化就是把顶点数据转换为像素片元的过程。像素片元中的每一个元素对应于渲染表面中的一个像素。

简而言之,光栅化就是将图形【graphics】变为图像【image】的过程。

还是有点学术化,解释如下:

  • 顶点数据(既矢量数据【vector】,或图形【graphics】),因为矢量或图形是以顶点【vertex】方式进行定义的。例如一条线段由起点/终点来定义,而三角形由三个点来确定。

  • 一条线两个点,然后渲染表面需要使用像素表示,所以必须将两个点变成一系列像素,这就是光栅化【rasterization】(点线面体各种光栅化算法)。

  • 上面解释使用像素片元(fragment)而不是像素,是因为像素仅仅包含三个信息:分量的大小(8/16/32等),分量的数量(3/4),分量的排列方式【就是像素格式】,但是片元包含更多信息,例如3D api在光栅话的过程中片元还带有深度信息,纹理坐标

位块传输(bit-block transfer,bitblt for short):

当我们将canvas2d中的rendersurface 绘制到显示区表面时,发生了位块传输操作

位块传输需要两个(源【source】/目标【destination】)内存表面(或位图,图像等等,反正就是具有大小和像素格式的内存块)。

能将源表面的全部或一部分区域像素色彩数据传输到目标表面的全部或一部分区域。

并非是简单的数据拷贝(copy),因为bitblt不止是原图拷贝,有可能是进行源和目标表面之间像素的与运算、或运算,异或运算等等

如果源表面和目标表面的size不一致的情况下,将源矩形中的位图拷贝到目标矩形中,可以扩展或压缩该位图使其与目标矩形尺寸吻合。这个过程中会使用各种过滤插值算法让颜色尽量平和过度。但是会导致图像发生形变,这也是为什么上一篇中发生了形变!

bitblit会尽可能使用硬件加速,如果实在不行,它们会使用具有很好优化手段的软件传输方法(例如有硬件加速,则使用硬件加速,没有硬件加速,但支持simd(单指令多数据流),则使用simd算法,最后不行,就直接内存操作,反正bitblit是极其核心的一个功能,每个操作系统或硬件供应商都有关键优化代码对其支持)

图形处理和图像处理的区别:

图形学: 输入的是模型顶点数据(矢量表示),输出是图像(像素)

图像学: 输入是像素,输出还是像素,对像素进行处理,例如ps中的各种滤镜,现在很流行的图像识别等等

两者完美的结合: AR技术(Augmented Reality) = 图像识别处理+图形渲染效果

聊了这么多,我们总结一下canvas中的绘图的流程:

  • elem size 以及rgba像素格式决定了canvas渲染表面分配的内存大小

  • 所有canvas2d 的绘图操作(文字/各种形体都是矢量),经过光栅化后,将顶点表示的数据生成了像素表示,最终填充到了渲染表面中

  • canvas2d中的drawImage函数并不进行光栅化,而是进行位块传输(bitblt),根据源表面和目标表面尺寸的不同,自动进行stretch blt操作

  • css 拥有一个虚拟坐标系统,可以适应各种位置和尺寸单位(px,cm,rem...),是上层表示,但是最后必须要转换成px表示,所以render surface最后需要进行位块传输,将结果像素传送到css size定义的显示表面上去

所以,对于<canvas>/<image>等具有elem size以及显示效果的元素,如果不想发生明显的变形,就需要掌握两个关键诀窍:

  1. 尽量规定elem size,不要使用css size。即使使用css size,尽量和elem size 一致

  2. 如果使用css size,为了不变形,请尽量和elem size 的纵横比(height/width)一致,这时候render surface stretch blt to destination surface的时候,会进行等比扩展或缩放,至少比例是正确的,不会明显变形(iphone的纵横比基本只有两个:1.5/1.78,相对android各式各样的纵横比,好多了,不过目前来说,主流的android机的纵横比基本都是1.78)

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

推荐阅读更多精彩内容