• Webcodecs解析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提供了一种解包和解码编码图像数据的方法

    构造函数

    特性

    方法

    使用步骤

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

    // 获取图片宽高
    const getDimensions = async blob => {
      return new Promise(resolve => {
        const img = document.createElement("img");
        img.addEventListener("load", e => {
          return resolve({  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

    引用

  • 相关阅读:
    ActiveMQ消息队列的使用及应用
    Spring的事务配置详解
    Spring容器与SpringMVC容器的区别与联系
    理解java的三大特性之多态
    构造方法是静态还是非静态?
    java 中类初始化,构造方法,静态成员变量,静态块的加载顺序
    window.onerror的总结
    git 合并分支到master
    swiper实现匀速无缝滚动
    针对vue中请求数据对象新添加的属性不能响应式的解决方法
  • 原文地址:https://www.cnblogs.com/suyuanli/p/16361644.html
Copyright © 2020-2023  润新知