转自 http://www.jiazhengblog.com/blog/2019/03/24/3407/
什么是 ImageBitmap
?
我们先来看规范上是怎么说的:
An
ImageBitmap
object represents a bitmap image that can be painted to a canvas without undue latency.
直接翻译过来就是:ImageBitmap
表示一个位图图像,可以绘制到 canvas 上,同时不会有较大的延迟。通过描述可以看出这个对象可以用来在 canvas 中绘制图像,同时性能也比常规的方法好。至于性能为什么好,好在哪里我会在后面讲述,下面我们先来了解一下这个对象以及如何创建并使用这个对象。
ImageBitmap
对象包含的属性和方法很少,只有 width
、height
两个属性,以及 close
方法。width
和 height
用来描述图像的宽度和高度,就像普通的 Image
对象一样。而 close
方法用来释放资源,降低内存消耗。
如何创建一个 ImageBitmap
?
通过全局的 createImageBitmap
方法可以创建一个 ImageBitmap
实例。该方法的原型有两个:
1 2 |
|
方法的参数如下:
image
:HTMLImageElement
|SVGImageElement
|HTMLVideoElement
|HTMLCanvasElement
|Blob
|ImageData
|ImageBitmap
|OffscreenCanvas
:原始的图像对象,可以看到常见的元素都能支持。sx
:number
:原始图像截取的x坐标。sy
:number
:原始图像截取的y坐标。sw
:number
:截取宽度。sh
:number
:截取高度。options
:可选的配置参数,参数如下:imageOrientation
:设置图像是否在 y 方向上取反。允许的值为none
(默认)或者flipY
。premultiplyAlpha
:设置图像是否提前将透明信息添加到其余颜色通道中。允许的值为none
、premultiply
或者default
(默认)。colorSpaceConversion
:设置是否转换颜色空间。允许的值为none
或者default
(默认)。default
表示可能会做默认的转换。resizeWidth
:设置输出的宽度。resizeHeight
:设置输出的高度。resizeQuality
:设置调整尺寸的质量。允许的值为pixelated
、low
(默认)、medium
或者high
。
方法返回一个 Promise
对象,需要通过 then
方法获得结果并处理后续操作。从这里也能看出创建过程是异步的。
一个简单的例子
1 2 3 4 5 6 7 |
|
通过 fetch
方法发起一个图片请求,接着利用 blob
方法得到一个 blob
对象,进而创建出一个 ImageBitmap 实例。
性能好在哪里?
不论是在 canvas 里绘制2d图像,还是在 WebGL 中创建纹理,当使用图像时浏览器会把图像做一次解码(decode)处理。这个解码也就是把图像的原始格式(比如 jpeg、png 等)统一转换为位图,即每个像素使用 RGB 或 RGBA 来描述。当图片尺寸比较大的时候,解码也会有一定的消耗,而且这个耗时是同步的。
在下面试验中页面加载了一个 2048 x 2048 大小的图片并创建纹理:
通过 Chrome 的 DevTools 发现调用 texImage2D
时会有20多毫秒的解码过程。使用 ImageBitmap
即可将这个同步解码的耗时去掉:
现在调用 texImage2D
不会再产生解码的耗时,但是纹理传输仍然需要时间。
在 Worker 中使用
ImageBitmap
可以在 Worker
中创建,这样我们可以将实例直接传给“主线程”。进一步减少了“主线程”处理的时间。
使用 Closure Compiler 编译遇到的问题。
最近在项目里使用 ImageBitmap 了,但用 Closure Compiler 编译的时候遇到报错,提示 createImageBitmap
方法未定义,更新版本即可解决该问题。更新后还存在警告,原来是编译器按照6个参数的函数原型做校验,而项目当中使用的是2个参数的方式。还有一点需要注意,options
中的属性需要用引号阔起来,否则会被编译器混淆。