iT邦幫忙

5

Files - 圖片轉換處理

此篇記錄一下圖片傳輸的學習筆記,也順便帶大家了解~

上傳圖片

首先建立一個上傳圖片的 input

// 加上 multiple 可上傳多個檔案
<input type="file" name="file" id="file" multiple>

上傳檔案後可以用 files 屬性抓出資料
files屬性
我們可以觀察到他是 FileList,並不是陣列,且裡面有檔名、類型、大小等等的詳細資料,接下來讀取檔案有兩種方法,分別是 Blob URLFileReader,以下分開介紹

Blob URL

當我們拿到 FileList 後可以使用 URL.createObjectURL() 方法將圖片轉為 Blob URL

const file = document.querySelector('#myfile').files[0]

URL.createObjectURL(file)
// blob:http://127.0.0.1:5500/f0c69bbc-e8d7-4ba8-aaf2-ab8ab794da28

我們拿到的 Blob URL 是指向當前記憶體位址,也就是說可以直接在網址輸入並檢視圖片

上傳圖片預覽

我們亦可使用 Blob URL 來直接實現圖片預覽功能
首先新增一個 img 供預覽圖片用

<input type="file" name="file" id="file">
<img id="img">

接下來設定監聽事件,在上傳時將圖片顯示出來

const myFile = document.querySelector('#file')

myFile.addEventListener('change', function(e) {
  const file = e.target.files[0]
  const img = document.querySelector('#img')
  img.src = URL.createObjectURL(file)
})

下載圖片

當然我們也可以使用 Blob URL 來下載自己上傳的圖片
我們改寫一下剛剛監聽的內容

const myFile = document.querySelector('#file')

myFile.addEventListener('change', function(e) {
  const file = e.target.files[0]
  // 創造一個 a 標籤
  const downloadLink = document.createElement('a')
  // 將 a 標籤的連結改為 Blob URL
  downloadLink.href = URL.createObjectURL(file)
  // 將下載的檔名設定為 file
  downloadLink.download = 'file'
  // 點擊標籤
  downloadLink.click()
})

如此一來上傳的同時也下載了圖片

FileReader

再來介紹另一個方法,FileReader 可以將檔案轉成各種格式

  • readAsText()
  • readAsDataURL() : 轉換成 Base64 編碼
  • readAsArrayBuffer()
  • readAsBinaryString()
const myFile = document.querySelector('#file')

myFile.addEventListener('change', function(e) {
  // 取得檔案
  const file = e.target.files[0]
  // 宣告 FileReader
  const reader = new FileReader()
  
  // 進行格式轉換
  
  // 檔案轉換完成後執行
  reader.onload = function() {
    // 可以用 reader.result 查看編譯結果
    console.log(reader.result)
  }
})

基本宣告方法皆相同,只差在轉換的格式不同,接下來就介紹一下格式

Text

Text 預設使用 UTF-8 的編碼,將檔案轉換成文字

DataURL ( Base64 )

DataURL 使用 Base64 直接將圖片編碼,因此檔案大小越大,編碼長度也就越長,不過他與 Blob URL 不同,因為不是記憶體位址,所以可以將圖片繪出,且同樣可以做到預覽圖片與下載的功能

<input type="file" name="file" id="file">
<img id="img">
const myFile = document.querySelector('#file')

myFile.addEventListener('change', function(e) {
  const file = e.target.files[0]
  const reader = new FileReader()
  // 轉換成 DataURL
  reader.readAsDataURL(file)
  
  reader.onload = function() {
    // 將圖片 src 替換為 DataURL
    img.src = reader.result
  }
})

也同樣能實現下載功能

const myFile = document.querySelector('#file')

myFile.addEventListener('change', function(e) {
  const file = e.target.files[0]
  const reader = new FileReader()
  // 轉換成 DataURL
  reader.readAsDataURL(file)
  
  reader.onload = function() {
    // 創造一個 a 標籤
    const downloadLink = document.createElement('a')
    // 將 a 標籤的連結改為 DataURL
    downloadLink.href = reader.result
    // 將下載的檔名設定為 file
    downloadLink.download = 'file'
    // 點擊標籤
    downloadLink.click()
  }
})

ArrayBuffer

ArrayBuffer 是一種原始二進制數據,可再將其編譯成 Blob

const myFile = document.querySelector('#file')

myFile.addEventListener('change', function(e) {
  const file = e.target.files[0]
  const reader = new FileReader()
  // 轉換成 ArrayBuffer
  reader.readAsArrayBuffer(file)
  
  reader.onload = function() {
    // 將 ArrayBuffer 轉成 Blob
    // 後方 type 可填入需要的類型
    const blob = new Blob([reader.result], { type: 'image/jpeg' })
    // 亦可將 Blob 再次轉成 Blob URL
    console.log(URL.createObjectURL(blob))
  }
})

亦可直接將 ArrayBuffer 編譯為 DataURL

const myFile = document.querySelector('#file')

myFile.addEventListener('change', function(e) {
  const file = e.target.files[0]
  const reader = new FileReader()
  // 轉換成 ArrayBuffer
  reader.readAsArrayBuffer(file)
  
  reader.onload = function() {
    // 將 ArrayBuffer 轉換為 字串
    const str = String.fromCharCode.apply(null, new Uint8Array(reader.result))
    // 將其組成 DataURL
    console.log('data:image/jpg;base64,' + btoa(str))
  }
})

BinaryString

BinaryString 已經被 W3C 棄用,所以不建議使用

canvas

圖片與 canvas 可以互相轉換,如果不知道 canvas 是甚麼的話可以參考這邊

圖片轉 canvas

不管是 Blob URL 還是 DataURL 都可以將其轉成 canvas 繪製,首先我們先建立一個 canvas,然後使用 drawImage 方法將其繪製出來,使用之前介紹的 Blob URL 或是 DataURL 方法皆可

<input type="file" name="file" id="file">
<canvas id="mycanvas"></canvas>

Blob URL

const myFile = document.querySelector('#file')
const canvas = document.getElementById('mycanvas')
const ctx = canvas.getContext('2d')

myFile.addEventListener('change', function(e) {
  const file = e.target.files[0]
  // 宣告一個新圖片
  let img = new Image()
  img.src = URL.createObjectURL(file)
  
  img.onload = function() {
    // 設定 canvas 寬高等同圖片
    canvas.width = img.width
    canvas.height = img.height
    // 將其繪製,並設定繪製的圖片寬高
    ctx.drawImage(img, 0, 0, img.width, img.height)
  }
})

DataURL

const myFile = document.querySelector('#file')
const canvas = document.getElementById('mycanvas')
const ctx = canvas.getContext('2d')

myFile.addEventListener('change', function(e) {
  const file = e.target.files[0]
  const reader = new FileReader()
  // 轉換成 DataURL
  reader.readAsDataURL(file)
  
  reader.onload = function() {
    // 宣告一個新圖片
    let img = new Image()
    // 將圖片 src 替換為 DataURL
    img.src = reader.result
    
    img.onload = function() {
      // 設定 canvas 寬高等同圖片
      canvas.width = img.width
      canvas.height = img.height
      // 將其繪製,並設定繪製的圖片寬高
      ctx.drawImage(img, 0, 0, img.width, img.height)
    }
  }
})

canvas 轉圖片

首先我們繪製一個 canvas

<canvas id="mycanvas" width="150" height="150"></canvas>
<img id="img">
const canvas = document.getElementById('mycanvas')
const ctx = canvas.getContext('2d')
canvas.width = 150
canvas.height = 150
ctx.fillRect(25, 25, 100, 100)

接下來使用 toDataURL 方法可將其轉為 DataURL

const img = document.getElementById('img')
const data = canvas.toDataURL('image/png')
img.src = data

轉換後也可使用上面學過的的功能下載唷!

canvas 轉 Blob

可以用 toBlob 的方法將其轉為 Blob

canvas.toBlob(function(blob) {
  console.log(blob)
})

canvas 轉 Uint8ClampedArray

同上先畫出 canvas 圖形,使用 getImageData 可以獲取 Uint8ClampedArray 的數據

ctx.getImageData(0, 0, 150, 150).data

其實圖片的處理就是各種編碼的轉換,只要熟悉各種資料類型與處理方式,就可以簡單的操控圖片囉!


1 則留言

0
marlin12
iT邦新手 3 級 ‧ 2019-07-10 20:15:10

文章裏好像把[圖片轉canvas]和[canvas轉圖片]這兩個標題倒轉了?

Ares iT邦新手 5 級‧ 2019-07-10 21:46:56 檢舉

感謝~已修正

我要留言

立即登入留言