關於上傳圖片你應該注意的事

set: 踩坑分享
tags: Web
category: Front-End
description: 關於上傳圖片你應該注意的事 (exif 方向)
created_at: 2022/05/26 07:00:00

cover image


前言

關於這個 exif , 在我碰到這問題之前還完全不知道這個東西,我一直以為上傳不就很單純,就算前端要預覽也就頂多加個像是 FileReader 之類的東西去讀取然後丟進 <img> 就結束了。

但是就在某一天,在有 QA 測試的環境下發生了上傳圖片但是方向錯誤的問題。


注意事項

較新的瀏覽器都會幫忙處理這個問題,而以下是 image-orientation 這個 CSS 屬性的支援度。 exif-cap

看上面這張圖,所以如果你想玩玩,可以考慮去下載舊版瀏覽器。

但是有趣的是,瀏覽器就算支援這個 image-orientation 的屬性,也只是單純支援這個屬性而已,有沒有幫你處理就是另一回事了(這一點會在之後貼上幾個測試案例)。

所以最好還是得依賴第三方的套件幫忙處理會比較安全。


問題 DEMO

image-orientation

可以看到這張圖中未處理的圖片是橫的(但實際上拍照時是直的)

在較新的瀏覽器會自動翻正,而沒有自動修正的瀏覽器也可以透過 image-orientation 去設定,但是如果真的舊到連 image-orientation 都不支援,那可能只能依賴套件了。


image-orientation 怎麼運作的?

這個屬性去決定圖片怎麼樣顯示的(方向),而他主要有兩個屬性,分別是

  • none: 不做任何修正(自己處理的意思)
  • from-image: 從 EXIF 的資訊做翻轉,這個也是預設值(?)

為什麼我放問號(?)呢,後面會說明


什麼是 EXIF 呢?

簡單說就是記錄著一些圖片資訊(metadata)的東西,大概長下面這樣。

ExifTool Version Number         : <不給你看>
File Name                       : <不給你看>
Directory                       : <不給你看>
File Size                       : <不給你看>
Zone Identifier                 : <不給你看>
File Modification Date/Time     : <不給你看>
File Access Date/Time           : <不給你看>
File Creation Date/Time         : <不給你看>
File Permissions                : <不給你看>
File Type                       : <不給你看>
File Type Extension             : <不給你看>
MIME Type                       : <不給你看>
Exif Byte Order                 : <不給你看>
Compression                     : <不給你看>
Resolution Unit                 : <不給你看>
Make                            : <不給你看>
Camera Model Name               : <不給你看>
Software                        : <不給你看>
Orientation                     : <不給你看>
Modify Date                     : <不給你看>
Y Cb Cr Positioning             : <不給你看>
F Number                        : <不給你看>
Maker Note Unknown Text         : <不給你看>
Exposure Time                   : <不給你看>
Sensing Method                  : <不給你看>
Sub Sec Time Digitized          : <不給你看>
Sub Sec Time Original           : <不給你看>
Sub Sec Time                    : <不給你看>
Focal Length                    : <不給你看>
Flash                           : <不給你看>
Light Source                    : <不給你看>
ISO                             : <不給你看>
Metering Mode                   : <不給你看>
Create Date                     : <不給你看>
Exposure Compensation           : <不給你看>
Date/Time Original              : <不給你看>
White Balance                   : <不給你看>
Aperture Value                  : <不給你看>
Exposure Mode                   : <不給你看>
Exposure Program                : <不給你看>
Shutter Speed Value             : <不給你看>
Components Configuration        : <不給你看>
Color Space                     : <不給你看>
Exif Version                    : <不給你看>
X Resolution                    : <不給你看>
Y Resolution                    : <不給你看>
Thumbnail Offset                : <不給你看>
Thumbnail Length                : <不給你看>
JFIF Version                    : <不給你看>
Image Width                     : <不給你看>
Image Height                    : <不給你看>
Encoding Process                : <不給你看>
Bits Per Sample                 : <不給你看>
Color Components                : <不給你看>
Y Cb Cr Sub Sampling            : <不給你看>
Aperture                        : <不給你看>
Image Size                      : <不給你看>
Megapixels                      : <不給你看>
Shutter Speed                   : <不給你看>
Create Date                     : <不給你看>
Date/Time Original              : <不給你看>
Modify Date                     : <不給你看>
Thumbnail Image                 : <不給你看>
Focal Length                    : <不給你看>
Light Value                     : <不給你看>

而方向應該就是看這一個資訊 Orientation


關於舊版瀏覽器的測試心得(?)

Firefox 為例,我總共載了幾個版本來測試XD

版本 自動修正 支援屬性 預設值
25 F F -
26 F T 0deg
63 F T none
64 F T none
99 T T from-image

上面可以看到,在比較新版的才支援自動修正,而比較舊的瀏覽器的預設值還不是 from-image ,所以我才會在最上面說明的時候打一個問號(?)


解決方案

  1. 自己去抓 exif 的方向值在自己做翻轉(太累了 跳過) 是有一些方式可以抓到這個資訊,有興趣可以自己看看:

一般來說抓出來數字如果合法,應該會是下面其中一種可能,然後再依據數字判斷如何翻回來。

    1             2
    ██████        ██████
    ██                ██
    ████            ████
    ██                ██
    ██                ██

      3             4
        ██        ██
        ██        ██
      ████        ████
        ██        ██
    ██████        ██████

      5             6
  ██████████    ██
  ██  ██        ██  ██
  ██            ██████████

      7             8
          ██    ██████████
      ██  ██        ██  ██
  ██████████            ██

上面的方法比較麻煩,所以可以採用套件完成。

  1. 使用套件 JavaScript-Load-Image

功用就跟名字一樣,用他讀取圖片的話,可以設定請他幫你調整,而且這樣的話連 Firefox 25 都支援。


最基本的用法

  1. 使用 Callback
loadImage(
  '<Blob object or image URL>',
  function (image) {

  },
  {
    orientation: true,
  }
)
  1. 使用 Promise
loadImage(
  '<Blob object or image URL>',
  {
    orientation: true,
  }
).then(data => {
  const image = data.image
})

這時候你就會拿到處理完的圖片了。




最後更新時間: 2022年05月26日.