【bigo前端】如何截取gif首帧图片

file

本文首发于:https://github.com/bigo-frontend/blog/ 欢迎关注、转载。

前言

先介绍一下js文件类型的知识点,后面要多次转换文件类型。

一.什么是Blob、File、DataURL

Blob 类型

Blob 类型是 File 文件类型的父类,它表示一个不可变、原始数据的类文件对象。
如何得到 blob 对象?

new Blob(array, options)
let hiBlob = new Blob([`<h1>Hi gauseen!<h1>`], { type: 'text/html' })

如上代码,就创建了一个 blob 对象,并声明了 text/html 类型 ,就像是创建一个 .html 文件。只不过它存在于浏览器的内存里。

File 类型

File 包含文件的相关信息,可以通过 js 来访问其内容

如何获取 file 对象?

1.new File(bits, name[, options])

// 1. 参数是字符串组成的数组
let hiFile = new File([`<h1>Hi gauseen!<h1>`], 'fileName', { type: 'text/html' })
// 2. blob 转 file 类型
let hiBlob = new Blob([`<h1>Hi gauseen!<h1>`], { type: 'text/html' })
let hiFile = new File([ hiBlob ], 'fileName', { type: 'text/html' })

如上代码,通过 File 构造函数,创建一个 file 对象,与上面的提到的 blob 类似。可以将 blob 转成 file 类型,这意味着上面获取的 blob,可以转成 file 类型。

2.inputElement.files

通过标签获取 file 对象

// input 上传文件时触发 change 事件
$('input').addEventListener('change', e => {
  let file = e.target.files[0]
  console.log('file: ', file)
})

3.DragEvent.dataTransfer.files

通过拖、放获取 file 对象

DataURL(base64)

DataURL,前缀为 data: 协议的 URL,可以存储一些小型数据

语法:data:[][;base64]

如下,黑色 1 像素示例:

data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs=

上面提到的 Blob File 类型,如何“消费”它们呢?接着向下看

1.FileReader

允许 Web 应用程序异步读取存储在用户计算机上的文件(blob 或 file)。

// 将 blob 或 file 转成 DataURL(base64) 形式
fileReader(someFile).then(base64 => {
  console.log('base64: ', base64)
})

function fileReader (blob) {
  return new Promise((resolve, reject) => {
    let reader = new FileReader()
    reader.onload = (e) => {
      resolve(e.target.result)
    }
    reader.readAsDataURL(blob)
  })
}

2.convasElement.toDataURL()

可以通过 canvas 图像处理能力,将图片转成 dataURL 形式。在上面 Blob 部分讲解中,代码已实现。

二.DataURL、File、Blob互转

DataURL转Blob对象

// DataURL转Blob对象
export function dataURLToBlob(dataurl, mine = 'image/jpeg'): Blob {
  const arr = dataurl.split(",");
  const mimeType = mine || arr[0].match(/:(.*?);/)[1];
  const bstr = atob(arr[1]);
  let n = bstr.length;
  const u8arr = new Uint8Array(n);
  while (n--) {
    u8arr[n] = bstr.charCodeAt(n);
  }
  return new Blob([u8arr], { type: mimeType });
}

DataURL转File对象

// DataURL转File对象
function dataURLtoFile(dataurl, filename, mine = 'image/jpeg') {
  const arr = dataurl.split(',');
  const mimeType = mine || arr[0].match(/:(.*?);/)[1];
  const bstr = atob(arr[1])
  let n = bstr.length;
  const u8arr = new Uint8Array(n);
  while(n--){
      u8arr[n] = bstr.charCodeAt(n);
  }
  return new File([u8arr], filename, {type:mimeType});
}

更多转换方式:https://blog.csdn.net/hahahhahahahha123456/article/details/80605836

三.gif截取插件SuperGif

原理:图象标识符(Image Descriptor)

一个GIF文件内可以包含多幅图象,一幅图象结束之后紧接着下是一幅图象的标识符,图象标识符以0x2C(’’,’’)字符开始, 定义紧接着它的图象的性质,包括图象相对于逻辑屏幕边界的偏移量、图象大小以及有无局部颜色列表和颜色列表大小, 由10个字节组成

开源插件:https://github.com/buzzfeed/libgif-js

四.antd upload组件处理

项目框架使用了antd,故需要在上传回调时进行首帧截取。
upload组件回调参数返回File类型

  1. file转换为dataUrl
  2. 新建img实例接收dataUrl数据
  3. 初始化SuperGif实例
  4. 截取首帧图片,返回dataUrl数据
  5. dataUrl转换为file数据
  6. 返回给业务接口,上传图片
export function getGIFFirstFrame(file): Promise<File> {
  return new Promise((resolve) => {
    const reader = new FileReader();
    reader.readAsDataURL(file);
    reader.onload = () => {
      const img = new Image();
      // @ts-ignore
      img.src = reader.result;
      img.onload = () => {
        // @ts-ignore
        const rub = new SuperGif({ gif: img });
        rub.load(function () {
          if (rub.get_length() === 0) {
            return;
          }
          // 获取gif实例的首帧
          rub.move_to(0);
          // canvas生成base64图片数据
          const dataurl = rub.get_canvas().toDataURL("image/jpeg", 0.8);
          const filename = file.name.replace('.gif', '.jpg');
          resolve(dataURLtoFile(dataurl, filename));
          return;
        });
      };
    };
  });
  
}

欢迎大家留言讨论,祝工作顺利、生活愉快!

我是bigo前端,下期见。

您好!要在Canvas生成GIF动画,您可以使用一些库或工具来帮助实现此功能。以下是一种常见的方法: 1. 首先,您需要将每一帧的图像绘制到Canvas上。您可以使用Canvas API的`drawImage`方法来加载每一帧的图像。 2. 将每一帧的图像保存为单独的Canvas对象或图像对象。 3. 使用一个库,比如gif.js(https://jnordberg.github.io/gif.js/),它是一个用于在浏览器生成GIFJavaScript库。您可以通过将每一帧的图像传递给gif.js来创建GIF动画。 4. 通过调用gif.js的方法来设置GIF的参数,例如帧速率、循环等。 5. 调用gif.js的`render`方法来生成GIF动画。 下面是一个简单的示例代码,演示如何使用gif.js在Canvas生成GIF动画: ```javascript // 创建一个GIF实例 var gif = new GIF({ workers: 2, quality: 10 }); // 获取Canvas元素和上下文 var canvas = document.getElementById("myCanvas"); var ctx = canvas.getContext("2d"); // 循环遍历每一帧 for (var i = 0; i < numFrames; i++) { // 在Canvas上绘制当前帧 drawFrame(i); // 将当前帧的Canvas对象添加到GIF实例 gif.addFrame(canvas, { delay: 200 }); } // 生成GIF动画 gif.render(); // 绘制每一帧的函数 function drawFrame(frameIndex) { // 清除Canvas ctx.clearRect(0, 0, canvas.width, canvas.height); // 绘制当前帧 // ... // 示例:在Canvas上绘制一个简单的矩形 ctx.fillStyle = "red"; ctx.fillRect(0, 0, canvas.width, canvas.height); } ``` 您需要根据您的具体需求和图像生成逻辑来调整代码。希望对您有所帮助!如果您有任何其他问题,请随时提问。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值