Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

【bigo】gif首帧图片截取 #2

Open
yeyeye0525 opened this issue Nov 4, 2020 · 0 comments
Open

【bigo】gif首帧图片截取 #2

yeyeye0525 opened this issue Nov 4, 2020 · 0 comments

Comments

@yeyeye0525
Copy link
Contributor

要先了解一下js文件类型的知识点,后面要多次转换数据结构,故先介绍一下。

1.什么是DataURL、File、Blob

Blob 类型

Blob 类型是 File 文件类型的父类,它表示一个不可变、原始数据的类文件对象

如何得到 blob 对象?

  1. 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 类型。

  1. inputElement.files

通过 标签获取 file 对象

// input 上传文件时触发 change 事件

$('input').addEventListener('change', e => {
  let file = e.target.files[0]
  console.log('file: ', file)
})
  1. 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)
  })
}
  1. convasElement.toDataURL()

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

2.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

3.gif截取插件SuperGif

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

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

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

4.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;
        });
      };
    };
  });
  
}
@yeyeye0525 yeyeye0525 changed the title gif首帧图片截取 【bigo】gif首帧图片截取 Nov 23, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant