使用PHP獲取影像檔案的EXIF資訊

船頭尺發表於2021-09-09

在我們拍的照片以及各類影像檔案中,其實還儲存著一些資訊是無法直觀看到的,比如手機拍照時會有的位置資訊,圖片的型別、大小等,這些資訊就稱為 EXIF 資訊。一般 JPG 、 TIFF 這類的圖片檔案都會有這樣的資訊。EXIF 其實就是專門為這種數碼照片所定製的,專門用於記錄數碼照片的屬性資訊和拍攝資料的,最初由日本製定。這個其實很好理解,日本對相機行業基本是壟斷般的存在,所以這類的標準當然就是由他們制定啦!

EXIF 在 Windows 系統中具有原生的支援,滑鼠右鍵點選圖片開啟選單,然後點選屬性並切換到詳細資訊就可以直接看到圖片檔案的 EXIF 資訊了。由於這些資訊是可以被隨意編輯的,所以它們可以作為一些參考,並不能作為某些功能屬性的確定值來獲取,比如寬高這些資訊就不要完全相信 EXIF 中的。

獲取 EXIF 中的圖片型別資訊

首先,我們看下透過 EXIF 來檢視圖片的型別。

var_dump(exif_imagetype($png)); // int(3)
echo exif_imagetype($png) == IMAGETYPE_PNG ? $png . '是 PNG 圖片' : $png . '不是 PNG 圖片', PHP_EOL;
// ../img/1.png是 PNG 圖片

var_dump(exif_imagetype($jpg)); // int(2)
echo exif_imagetype($jpg) == IMAGETYPE_JPEG ? $jpg . '是 jpg 圖片' : $jpg . '不是 JPG 圖片', PHP_EOL;
// ../img/2.jpg是 jpg 圖片

直接使用 exif_imagetype() 函式就會返回一個圖片型別的常量,也就是以 IMAGETYPE_ 開頭的常量資訊所代表的圖片型別。它還包括其它很多型別,這裡只是演示了我們平常最常見的 jpg 和 png 型別的圖片型別的獲取。

它和 getimagesize() 函式返回的第三個屬性,也就是下標為 2 的那個屬性的內容是一樣的,在 getimagesize() 函式中,0 和 1 代表的是寬高,2 代表的就是圖片的型別。

var_dump(getimagesize($jpg));
// array(7) {
//     [0]=>
//     int(300)
//     [1]=>
//     int(244)
//     [2]=>
//     int(2)
//     [3]=>
//     string(24) "width="300" height="244""
//     ["bits"]=>
//     int(8)
//     ["channels"]=>
//     int(3)
//     ["mime"]=>
//     string(10) "image/jpeg"
//   }

獲取完整的 EXIF 資訊

圖片中完整的所有 EXIF 資訊是透過 exif_read_data() 函式來獲取的。

var_dump(exif_read_data($png));
// PHP Warning:  exif_read_data(1.png): File not supported in /Users/zhangyue/MyDoc/部落格文章/dev-blog/php/202011/source/11.使用PHP獲取影像檔案的EXIF資訊.php on line 14

// Warning: exif_read_data(1.png): File not supported in /Users/zhangyue/MyDoc/部落格文章/dev-blog/php/202011/source/11.使用PHP獲取影像檔案的EXIF資訊.php on line 14

// bool(false)

var_dump(exif_read_data($jpg));
// array(8) {
//     ["FileName"]=>
//     string(5) "2.jpg"
//     ["FileDateTime"]=>
//     int(1605061174)
//     ["FileSize"]=>
//     int(19075)
//     ["FileType"]=>
//     int(2)
// ……
// ……

就像前面講過的,EXIF 資訊只在 JPG 、 TIFF 等型別的圖片格式中存在,所以 PNG 圖片是無法獲取到 EXIF 資訊的。如果對 PNG 圖片使用 exif_read_data() 就會報出警告。而對於 JPG 來說,就會返回完整的全部的 EXIF 內容。這裡我們只擷取了一部分,本身的內容非常多,不只是寬、高、型別、壓縮比率之類的,如果是手機拍攝的還能看到手機廠商、地理位置、快門引數、光圈引數等,當然,這個也和你使用的相機有很大的關係,有的廠家可能就會少一些資料。這個大家可以自己拍張照然後使用這個函式來自己檢視一下。

另外,還有一個別名函式 read_exif_data() ,與 exif_read_data() 的功能是類似的,就是它的一個別名,並且在 PHP7 以後就已經標記為過時的語法了。大家可以瞭解一下。

var_dump(read_exif_data($jpg));
// PHP Deprecated:  Function read_exif_data() is deprecated in /Users/zhangyue/MyDoc/部落格文章/dev-blog/php/202011/source/11.使用PHP獲取影像檔案的EXIF資訊.php on line 17

// Deprecated: Function read_exif_data() is deprecated in /Users/zhangyue/MyDoc/部落格文章/dev-blog/php/202011/source/11.使用PHP獲取影像檔案的EXIF資訊.php on line 17
// array(8) {
//   ["FileName"]=>
//   string(5) "2.jpg"
//   ["FileDateTime"]=>
//   int(1605061174)
//   ["FileSize"]=>
// ……
// ……

獲取指定索引的頭名稱

索引頭對應的就是 EXIF 中的欄位名稱,我們可以檢視當前所有支援的索引頭資訊,內容非常多。也可以根據索引頭獲得屬性名稱,然後再到 EXIF 中查詢對應的屬性資訊。

echo "256: " . exif_tagname(256) . PHP_EOL;
// 256: ImageWidth
for ($id = 1; $id  65535; $id++) {
    if (exif_tagname($id) != "") {
        echo $id . ' ( ' . exif_tagname($id) . ' )', PHP_EOL;
    }
}
// 11 ( ACDComment )
// 254 ( NewSubFile )
// 255 ( SubFile )
// 256 ( ImageWidth )
// 257 ( ImageLength )
// 258 ( BitsPerSample )
// 259 ( Compression )
// ……
// ……
// ……

讀取 JPG 檔案中嵌入的縮圖

可能很多人不知道吧,EXIF 中是可以儲存一個縮圖的。而且大家的手機拍出來的相片基本都會有這個縮圖存在。Windows 系統中如果圖片有縮圖的話也會直接用 EXIF 中的縮圖,如果沒有的話,就會自動在目錄中生成一個 Thumbs.db 檔案,也就是一個縮圖的資料庫。

var_dump(exif_thumbnail('../img/3.jpeg'));
// string(14369) "�����

//                         !"$��@"���

// }!1AQa"q2��#B��R��$3br�
// %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz�������������������������������������������������������������������������

// w!1AQaq"2B����  #3R�br�
// $4�%�&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz��������������������������������������������������������������������������
//                                                                                                                           ?�b�������������?J�l�2

file_put_contents('../img/3-thumbnail.jpeg', exif_thumbnail('../img/3.jpeg'));

在 PHP 中可以透過 exif_thumbnail() 這個函式直接獲取 JPG 檔案中 EXIF 裡面儲存的縮圖資訊。在測試程式碼中我們獲取到後再將它儲存為正式的圖片,大家就可以看到縮圖的真實樣子了。並且我們使用 exif_read_data() 來讀取這個檔案的話,也能看到縮圖儲存的資訊。

var_dump(exif_read_data('../img/3.jpeg'));
// array(56) {
// ……
// ……
// ……
//     ["Make"]=>
//     string(6) "Xiaomi"
//     ["THUMBNAIL"]=>
//     array(9) {
//       ["JPEGInterchangeFormat"]=>
//       int(5504)
//       ["Orientation"]=>
//       int(6)
//       ["JPEGInterchangeFormatLength"]=>
//       int(14369)
//       ["Compression"]=>
//       int(6)
//       ["ResolutionUnit"]=>
//       int(2)
//       ["XResolution"]=>
//       string(4) "72/1"
//       ["YResolution"]=>
//       string(4) "72/1"
//       ["ExifImageLength"]=>
//       int(240)
//       ["ExifImageWidth"]=>
//       int(320)
//     }
//     ["UndefinedTag:0x9AAA"]=>
//     string(4480) "1y�L�=w%�s_�&��v��oJ��$Gdz|d�9n�
//   �������~��+9����2V:+�о�Qn]�۲͐� ��U��nwF��w;f�h�k���i*w�bd+�D0�=o��y����x�,��BS��#/d�9���˓
//                                                                                             ,%C�3���eIZ~��������oLܰܡ~�}#�y:4Ӥ}�    ��dȻGI*Y��
//                                                                                                                                             ��m�)��x#a�6J
//           w       W�"E�c���OV�l9����                                                                                                                                        p�f�����KAFUg���
//   ����U�ޘ�CO�>ʈ7��ݪG�T&,� Ie�%�
  
//   ?��S���§�9��6s��8LT&o
//   Vn�Џ�R��c6��Ϝ p�G�f#��/�o����_�@�$�%#
//                                        � �Ҡ��5v��~����Ȣ)�ڽa�i�:����}��3xKM�CIe�����5&�/��䇃�隙R�+��He��}���b�Ґ�?
// ……
// ……
// ……

總結

對於圖片的 EXIF 有了一個基本的瞭解了吧。今天學習的需要注意的幾點是:一是 EXIF 只有 JPG 、 TIFF 這類的圖片格式上才有,二是它們是可修改的,三是這玩意裡面竟然還能儲存一張縮圖。果然,學習就是個無底洞,一不小心又開了眼界了。加油吧,少年們!=

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/3016/viewspace-2796765/,如需轉載,請註明出處,否則將追究法律責任。

相關文章