当前位置 : 主页 > 编程语言 > 其它开发 >

Webcodecs解析GIF图

来源:互联网 收集:自由互联 发布时间:2022-06-10
使用浏览器原生API解析GIF图,可以实现控制动图播放速度,次数等能力 Webcodecs解析GIF图什么是GIF GIF格式的名称是Graphics Interchange Format的缩写,是在1987年由Compu Serve公司为了填补跨平台
Webcodecs解析GIF图 使用浏览器原生API解析GIF图,可以实现控制动图播放速度,次数等能力 Webcodecs解析GIF图 什么是GIF

GIF格式的名称是Graphics Interchange Format的缩写,是在1987年由Compu Serve公司为了填补跨平台图像格式的空白而发展起来的。GIF可以被PC和Mactiontosh等多种平台上被支持。

GIF是一种位图。位图的大致原理是:图片由许多的像素组成,每一个像素都被指定了一种颜色,这些像素综合起来就构成了图片。GIF采用的是Lempel-Zev-Welch(LZW)压缩算法,最高支持256种颜色。由于这种特性,GIF比较适用于色彩较少的图片,比如卡通造型、公司标志等等。如果碰到需要用真彩色的场合,那么GIF的表现力就有限了。GIF通常会自带一个调色板,里面存放需要用到的各种颜色。在Web运用中,图像的文件量的大小将会明显地影响到下载的速度,因此我们可以根据GIF带调色板的特性来优化调色板,减少图像使用的颜色数(有些图像用不到的颜色可以舍去),而不影响到图片的质量。

GIF格式和其他图像格式的最大区别在于,它完全是作为一种公用标准而设计的,由于Compu Serve网络的流行,许多平台都支持GIF格式。Compu Serve通过免费发行格式说明书推广GIF,但要求使用GIF文件格式的软件要包含其版权信息的说明。

在平时的开发中经常会遇到需要控制gif图暂停播放、或者控制播放次数的需求,这个看起来很正常的需求在前端实现其实不太简单,因为浏览器提供的能力只有通过 标签循环播放GIF图,如果要控制的话往往需要引入gif-decoder的库去解析gif图,在将其作为帧动画进行播放控制。

不过现在已经是2022年了,chrome在94开始提供了Webcodecs的ImageDecoder解析GIF图,不需要借助外力了,我们可以提前熟悉起来了

image-20220608231046235

什么是Webcodecs

WebCodecs API为 Web 开发人员提供了对视频流的各个帧和音频块的低级访问。它对于需要完全控制媒体处理方式的 Web 应用程序很有用。例如,视频或音频编辑器以及视频会议

许多 Web API 在内部使用媒体编解码器。例如Web Audio API, 和WebRTC API。然而,这些 API 不允许开发人员处理视频流的单个帧和未混合的编码音频或视频块。

Web 开发人员通常使用 WebAssembly 来绕过这个限制,并在浏览器中使用媒体编解码器。但是,这需要额外的带宽来下载浏览器中已经存在的编解码器,从而降低性能和电源效率,并增加额外的开发开销。

WebCodecs API 提供对浏览器中已有编解码器的访问。它可以访问原始视频帧、音频数据块、图像解码器、音频和视频编码器和解码器。

从上面描述可以了解到Webcodecs是提供给开发者处理音视频和图片的,可以让开发者可以直接通过浏览器api解析音视频抽出视频帧直接在canvas上显示出来。不过目前支持的音视频编码格式很有限,可以说是在实际开发场景中几乎无法使用,单单音频编码不支持AAC基本已经把大部分的主流web视频给嘎了。

不过Webcodecs提供了一个ImageDecoder 倒是很实用的,它可以解析GIF图,得到gif图的所有帧图片。

ImageDecoder

ImageDecoder接口是Webcodecs提供了一种解包和解码编码图像数据的方法

构造函数

  • ImageDecoder()

    创建一个新ImageDecoder对象。

特性

  • ImageDecoder.complete只读

    返回一个boolean指示数据是否完全缓冲的值。

  • ImageDecoder.completed只读

    返回一次Promise解析complete为真的 a。

  • ImageDecoder.tracks只读

    返回一个ImageTrackList列出可用轨道并提供选择要解码的轨道的方法的对象。

方法

  • ImageDecoder.close()

    结束所有待处理的工作并释放系统资源。

  • ImageDecoder.decode()

    将控制消息排入队列以解码图像的帧。

  • ImageDecoder.reset()

    重置所有状态,包括配置、控制消息队列中的控制消息以及所有挂起的回调。

使用步骤

1.获取GIF图的buffer和宽高(用设置canvas宽高)

// 获取图片宽高
const getDimensions = async blob => {
  return new Promise(resolve => {
    const img = document.createElement("img");
    img.addEventListener("load", e => {
      return resolve({ width: img.naturalWidth, height: img.naturalHeight });
    });
    img.src = URL.createObjectURL(blob);
  });
};

// 获取gif buffer
const getGifBuffer = async (url) => {
    const response = await fetch(url);
    const clone = response.clone();
    const blob = await response.blob();
    const { width, height } = await getDimensions(blob);
    canvas.width = width;
    canvas.height = height;
    return clone.body
}

2.实例化ImageDecoder和获取当前选中的轨道
const imageDecoder = new ImageDecoder({
    data: imageByteStream,
    type: 'image/gif',
}); 
// imageDecoder.tracks为轨道集,selectedTrack为选中轨道,可以通过track.frameCount获取GIF图总共有多少帧
const track = imageDecoder.tracks.selectedTrack;
3.获取某一帧图片并绘制
const renderImage = async (frameIndex) => {
    const imageFrame = await imageDecoder.decode({frameIndex: imageIndex});
    ctx.drawImage(imageFrame.image, 0, 0);
}
4.循环渲染所有帧图
const run = async (imageIndex) => {
    if (imageIndex + 1 >= track.frameCount) {
        imageIndex = 0;
    }
    await renderImage(imageIndex);
    window.setTimeout(() => {
    	run(imageIndex + 1);
    }, 50);
}
run(0)

上面是分步骤的一个实现主要是,完整的代码例子可以参考下面的地址,效果如下,我们可以做到控制gif播放速度,增加滤镜等能力

gif解析demo

tt2

引用
网友评论