JS图片对象转换函数(File\DataURL\ObjectURL\Image\Canvas)

前言

我们前面已有多篇文章介绍了前端文件和图像操作相关的知识,这些博文对我们如何处理图像文件,提供了一些基础和原理性的知识,能够帮助我们更了解所需要使用到的图片文件和相应对象处理。
本文将在之前的基础上,提炼出前端图像文件操作中存在的各个对象之间的转换方法,这将有利于我们更加深入的理解图像知识,并且方便在实际项目中直接使用对应的方法。

图像数据类型

当前我们在前端JS中处理图像时,大致有四种不同的图像数据类型:

  • 文件
    • Blob:该对象表示的是一个不可变、原始数据的类文件对象,本质上是一个二进制对象
    • File:继承自Blob对象,是一种特殊类型的Blob,它扩展了对系统文件的支持能力
    • ArrayBuffer:表示通用的、固定长度的原始二进制缓冲区
  • URL
    • Data-URL:带Base64字符串编码的图像资源
    • Object-URL:浏览器存储的Blob对象,并维护生成的一个图像资源
    • Http-URL:存储于服务器上的图像资源
    • 本地图片:本地图像资源
  • Image:img(HTMLImageElement)
    DOM标签 <img> 对应的对象和类型,用于加载图像资源
  • Canvas:canvas(HTMLCanvasElement)、ImageData、ImageBitmap
    DOM标签 <canvas> 对应的对象和类型,用于加载图像资源和操作图像数据

各个API对象与相应的知识,可见以下博文,
Blob、Object-URL等内容, 前端二进制处理相关的(如Blob、File、Object-URL)
文件上传读取的方式, web前端文件上传可选择的4种方式
Base64相关的知识(Data-URL), Base64编解码知识详解(Data-URL)
Dom对象相关的API接口, 前端图片处理API总结(如Image、ImageData)
前端需要了解的图片基础知识, 图片基础介绍与前端支持的格式

转换方法

下面我们从前端图像加载的数据类型上,介绍各自类型之间一一对应的转换方法,其中有些类型之间可以直接转换,有些则需要使用第三方类型进行间接转换。

直接转换

使用Web-API对象,可以直接将上传的File(Blob)对象转换成URL类型的,主要是Data-URL(Base64图像字符串)和Object-URL。

File 转 Data-URL

这个过程需要使用到 FileReader 文件读取对象,通过 readAsDataURL() 方法将读取到的文件内容转换成Base64字符串,以 Data-URL 的格式输出。
由于FileReader对象实例,是异步加载文件内容,所以我们通过 Promise 的方式返回:

function file2DataURL(file) {
    
    
  return new Promise(resolve => {
    
    
    const reader = new FileReader()
    reader.onload = () => {
    
    
      resolve(reader.result)
    }
    reader.readAsDataURL(file)
  })
}

File 转 Object-URL

将File对象转为 Object-URL,则直接使用 URL.createObjectURL() 就可以转换了:

function file2ObjectURL(file) {
    
    
  const url = URL.createObjectURL(file)
  return url
}

注意,我们需要手动释放 Object-URL,通过 URL.revokeObjectURL(url) 方法。

Url/Data-URL/Object-URL 转 Image

加载图像的URL资源数据后,转换成Image对象。
Image对象能够加载四种类型的图像资源:本地路径、网络地址、Data-URL 和 Object-URL。他们的加载方式都是一样的,也同样是异步加载:

function url2Image(url) {
    
    
  return new Promise(resolve => {
    
    
    const image = new Image()  
    image.onload = () => {
    
    
      resolve(image)
    }
    image.src = url
  })
}

Url/Data-URL/Object-URL 转 Blob

在服务接口请求中,我们可以将url转换成blob对象,使用 XHRfetch 都可以达成目标:

async function url2Blob (url) {
    
    
  return await (await fetch(url)).blob()
}

Image 转 Canvas

主要将Image直接绘制到Canvas中。
Image实例作为HTMLImageElement对象类型,可以被直接绘制到canvas中,转换也很容易:

function image2Canvas(image) {
    
    
  const canvas = document.createElement('canvas')
  const ctx = canvas.getContext('2d')
  canvas.width = image.width
  canvas.height = image.height
  ctx.drawImage(image, 0, 0)
  return canvas
}

Canvas 转 Data-URL

toDataURL()方法可以把Canvas转换成Data-URL:

function canvas2DataURL(canvas) {
    
    
  return canvas.toDataURL()
}

语法:canvas.toDataURL(mimeType, quality)
参数:

  • mimeType:可选,图像的mimeType类型。默认值是 image/png
  • quality:可选,表示图像质量,范围0-1,默认0.92,对jpg和webp有效。对png格式无效。

Canvas 转 Blob

要把Canvas转化成Blob,可以直接使用Canvas的方法 toBlob()
这里得到的Blob可以直接当做File来使用,使用 FileReaderURL.createObjectURL() 进行处理:

function canvas2Blob(canvas) {
    
    
  return new Promise(resolve => {
    
    
    canvas.toBlob((blob) => {
    
    
      resolve(blob)
    })
  })
}

语法:void canvas.toBlob(callback, mimeType, quality)
参数:

  • callback:成功后的回调函数
  • mimeType:可选,图像的mimeType类型。默认值是 image/png
  • quality:可选,表示图像质量,范围0-1,默认0.92,对jpg和webp有效。对png格式无效。

间接转换

以上的方法,都是在几个对象之间进行单个API的直接转换,下面则是需要进行多个方法的组合,使用第三个对象中转,才能正确转换。

File 转 Image

从上文可知,File对象可以直接转换成 Data-URL 或 Object-URL,这样就能中转成Image:

方案一,先转成Object-URL,再加载Image:

async function file2Image(file) {
    
    
  const objUrl = file2ObjectURL(file)
  const img = await url2Image(objUrl)
  URL.revokeObjectURL(objUrl)
  return img
}

方案二,先转成Data-URL,再加载Image::

async function file2Image(file) {
    
    
  const dataUrl = await file2DataURL(file)
  const img = await url2Image(dataUrl)
  return img
}

File 转 Canvas

方案一,createImageBitmap() 方法可以读取File对象,并返回Canvas能够接收的图像对象 ImageBitmap,并写入到canvas中:

async function file2Canvas(file) {
    
    
  const imageBitmap = await createImageBitmap(file)
  const canvas = document.createElement('canvas')
  canvas.width = imageBitmap.width
  canvas.height = imageBitmap.height
  const ctx = canvas.getContext('2d')
  ctx.drawImage(imageBitmap, 0, 0)
  return canvas
}

ImageBitmap 表示位图图像,拥有宽高属性,能够被绘制到Canvas中。
drawImage() 可以接收 HTMLImageElement、ImageBitmap等对象作为数据源,绘制到画布中。

方案二,使用Image中转:

async function file2Canvas(file) {
    
    
  const img = await file2Image(file)
  const canvas = image2Canvas(img)
  return canvas
}

Canvas 转 Image

Canvas有了 toDataURL()toBlob() 方法,要转换成Image就非常方便了,结合以上已有的方法。

方案一,通过Blob中转:

async function canvas2Image(canvas) {
    
    
  const blob = await canvas2Blob(canvas)
  const img = await file2Image(blob)
  return img
}

方案二,通过Data-URL中转:

async function canvas2Image(canvas) {
    
    
  const dataUrl = canvas2DataURL(canvas)
  const img = await url2Image(dataUrl)
  return img
}

Data-URL(Base64) 转 Blob

方案一,直接解析Base64字符串数据,进行转换:

function dataURL2Blob(dataUrl) {
    
    
  const bsArr = dataUrl.split(',')
  const pattern = /^data:(.*?)(;base64)/
  const type = bsArr[0].match(pattern)[1]
  const dataStr = atob(bsArr[1])
  const len = dataStr.length
  const uint8Array = new Uint8Array(len)
  for (let i = 0; i < len; i++) {
    
    
    uint8Array[i] = dataStr.charCodeAt(i)
  }

  return new Blob([uint8Array], {
    
     type })
}

方案二,通过多个方法进行中转:

async function dataURL2Blob(dataUrl) {
    
    
  const img = await url2Image(dataUrl)
  const canvas = image2Canvas(img)
  const blob = await canvas2Blob(canvas)
  return blob
}

方案二里也有DataURL到Canvas的转换。

总结

我们在前端开发中,常用的转换一般是在 File、Image、Canvas 等几个主要对象之间展开,通过不同的形式加载不同的图像资源,有助于我们展示图片或者处理图像数据。
以上给出的方法,都是可以直接使用的,在我们操作这些对象时,根据需求调用即可。

猜你喜欢

转载自blog.csdn.net/jimojianghu/article/details/128716604
今日推荐