本篇的目的是要了解:

canvas 像素格式

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

光栅化

位块传输

图形和图像的区别

上一篇我们了解到: 当css size和 elem 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定义的显示表面上去

所以,对于/等具有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)

android表面渲染 哔哩,JS学习:创建一个演示用的渲染库4(渲染表面,像素格式等)...相关推荐

  1. 用SVG和Vanilla JS框架创建一个“星形变心形”的动画效果

    在我写的这篇文章中, 讲述了如何用Vanilla JavaScript使动画顺滑的从一种状态过渡到另一种.最好先看下那篇文章,因为在这篇文章中我们要用到一些那篇文章中讲过的内容.例如例子的演示.各种时 ...

  2. android 7 创建文件夹,Android 在 res/layout 文件夹 下创建一个 子文件夹实例

    Android 资源文件夹 Layout 文件夹 Layout 文件是存放Android的布局文件的资源文件夹,但是如果你想要在里面创建子文件夹,你会发现xml文件报错. 如何在Layout文件夹下方 ...

  3. ROS学习-创建一个ROS msg和一个srv

    目录 ROS msg和srv的介绍 使用msg 创建一个msg 使用rosmsg命令 使用srv 创建一个srv 使用rossrv命令 msg和srv的通用步骤 使用Help 简要总结回顾 ROS m ...

  4. outlook自动保存html,当创建一个新的HTML电子邮件时保持默认的Outlook格式

    我想创建一个简单的脚本来创建一个HTML消息,并且我想保留尽可能多的默认值.当创建一个新的HTML电子邮件时保持默认的Outlook格式 在我的情况下,当我使用Home创建一个新邮件->新邮件时 ...

  5. react.js app_在React.JS中创建一个Weather App

    react.js app Hello readers! 各位读者好! In this article, you will know how to develop a basic weather app ...

  6. android 根目录uri,如何在根目录下创建一个文件夹Android

    我需要在根目录下创建CAT_IMG文件夹,并在列表视图中检索它.但CAT_IMG文件夹不在根目录中创建.我在清单文件中添加了权限.请帮我在根目录下创建一个文件夹.如何在根目录下创建一个文件夹Andro ...

  7. html+js画一颗心形,用SVG和Vanilla JS框架创建一个“星形变心形”的动画效果

    在我写的这篇文章中, 讲述了如何用Vanilla JavaScript使动画顺滑的从一种状态过渡到另一种.最好先看下那篇文章,因为在这篇文章中我们要用到一些那篇文章中讲过的内容.例如例子的演示.各种时 ...

  8. Nexus.js介绍:一个多线程的JavaScript运行库

    首先,如果你不熟悉这个项目,建议先阅读之前写的一系列文章.如果你不想阅读这些,不用担心.这里面也会涉及到那些内容. 现在,让我们开始吧. 去年,我开始实现Nexus.js,这是一个基于Webkit/J ...

  9. Electron学习-创建一个程序

    Electron - 第一个程序 创建项目的时候我使用了Webstrom File -> New Project -> Node.js Express App (create) 大约一分钟 ...

最新文章

  1. C/C++代码静态检查工具PC-lint在VS2008开发环境中的安装配置和使用
  2. String和StringBuilder
  3. NYOJ--2--括号配对问题
  4. zabbix3.4搭建钉钉报警
  5. 开机启动加载驱动过程中调用PostMessage函数出错
  6. PKCS5Padding与PKCS7Padding的区别
  7. Flutter web问题:Failed to load network image
  8. django mysql 2006_Django (2006, 'MySQL server has gone away') 本地重现与解决
  9. window location href 手机端无法跳转_Window对象在前端领域的角色
  10. 如何将exe文件在linux下执行,如何在Linux系统下查找可执行文件
  11. Win7旗舰版系统如何设置定时关机
  12. linux 禁止其他用户登录,在Linux中如何禁止用户登录
  13. [Android学习笔记四] 自定义Android组件之组合方式创建密码框组件
  14. 《javascript入门学习笔记全集》【汇总】
  15. python图像颜色反转_OpenCV图像颜色反转算法详解
  16. 零基础CSS入门教程(7)——CSS外联写法
  17. 华为云服务的使用方法详解--以照片备份与恢复为例
  18. ensp MSTP实验搭建
  19. 股票买卖明细接口是怎样实现查询交易数据的?
  20. python 处理锯齿波信号

热门文章

  1. uniapp 隐藏滚动条
  2. 关于OA中权限越级的问题
  3. 发丝级别抠图算法重磅开源!
  4. 【Int、Fix】Int、Fix 函数的区别
  5. 机器学习之十九(读书笔记)
  6. 注释Java搞笑图_程序员的幽默感, 都藏在这些奇葩搞笑的代码注释里了
  7. python实现图书管理系统(超详细)
  8. UVa 10391 Compound Words(复合词)
  9. iOS 优化之NSTimer
  10. 五福来,新年到,2021年支付宝集五福最全攻略