使用PHP获取图像文件的EXIF信息-程序员宅基地

技术标签: python  java  xml  linux  html  

使用PHP获取图像文件的EXIF信息

在我们拍的照片以及各类图像文件中,其实还保存着一些信息是无法直观看到的,比如手机拍照时会有的位置信息,图片的类型、大小等,这些信息就称为 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<���2�z�B3���2�Ol*8
//           w       W�"E�c���OV�l9����                                                                                                                                        p�f�����KAFUg���<I���ʯ9E�S�
//   ����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 这类的图片格式上才有,二是它们是可修改的,三是这玩意里面竟然还能保存一张缩略图。果然,学习就是个无底洞,一不小心又开了眼界了。加油吧,少年们!

测试代码:

https://github.com/zhangyue0503/dev-blog/blob/master/php/202011/source/11.使用PHP获取图像文件的EXIF信息.php

参考文档:

https://www.php.net/manual/zh/book.exif.php

https://baike.baidu.com/item/Exif/422825?fr=aladdin

http://www.360doc.com/content/13/0223/14/9290626_267432131.shtml

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/zhangyue0503/article/details/119122958

智能推荐

Fibonacci Heap实现_fibonacciheap consolidate-程序员宅基地

文章浏览阅读740次。本算法是对<算法导论>相关章节伪代码的实现:先贴代码:#include#include#includeusing namespace std;class FibonacciHeap;class node{ friend class FibonacciHeap; node(int v):key(v),height(0),parent(NULL),left(this),righ_fibonacciheap consolidate

CSS选择器_css选择包含某个类名的节点-程序员宅基地

文章浏览阅读629次。1.简单选择器类选择器 使用时 .类名{样式1;样式2;},匹配对应类名元素 id选择器 使用时 #id{样式1;样式2;},匹配对应id的元素 标签选择器 使用时 标签名{样式1;样式2;},匹配对应标签的元素 通用元素选择器 使用时 *{样式1;样式2;},匹配所有元素 2.属性选择器以下标签名以div为例标签名[name] 所有含有name属性的di..._css选择包含某个类名的节点

ubuntu两个conda安装和切换-程序员宅基地

文章浏览阅读1.5k次。1. 下载anaconda2安装,一路默认,注意添加/home/wang/.bashrc选择yes2. 在/home/wang/envs/py3安装anaconda3,其他同anaconda23. conda create --name xxx27 python=2.7 (我的是myPy27),实际上我的包名是2.7.14版本4. conda create --name xxx36 ..._ubuntu 两个版本conda如何指定一个

计算机网络(自顶向下)第七章总结_移动性代理通告扩展中指出该代理是它所在网络的一个外部代理的字段是-程序员宅基地

文章浏览阅读1.4k次,点赞10次,收藏12次。计算机网络第七章:无线网络和移动网络7.1 概述无线网络要素:无线主机。如同在有线网络中一样,主机是运行应用程序的端系统设备。无线链路。主机通过无线通信链路 (wireless communication link) 连接到一个基站或者另一台无线主机。不同的无线链路技术具有不同的传输速率和能够传输不同的距离。基站。基站在有线网络中没有明确的对应设备。它负责向与之关联的无线主机发送数据和从主机那里接收数据。一台无线主机与某基站“相关联”,则是指①该主机位于该基站的无线通信覆盖范围内。②该主机_移动性代理通告扩展中指出该代理是它所在网络的一个外部代理的字段是

Gradle文件操作基础_gradle ziptree-程序员宅基地

文章浏览阅读1w次。一、定位文件:我们可以使用Project.file()方法来定位一个文件获取File对象(详情参考Project的API),如下://相对路径File configFile = file('src/config.xml')//绝对路径File configFile = file(configFile.absolutePath)//项目路径的文件对象 File config_gradle ziptree

张量分解总览_hooi算法-程序员宅基地

文章浏览阅读2k次,点赞3次,收藏14次。一般一维数组,我们称之为向量(vector),二维数组,我们称之为矩阵(matrix);三维数组以及多位数组,我们称之为张量(tensor)。 在介绍张量分解前,我们先看看矩阵分解相关知识概念。一、基本概念矩阵补全(Matrix Completion)目的是为了估计矩阵中缺失的部分(不可观察的部分),可以看做是用矩阵X近似矩阵M,然后用X中的元素作为矩阵M_hooi算法

随便推点

滥用图片博客做 C&C 配置-程序员宅基地

文章浏览阅读60次。0xCC · 2016/02/03 14:500x00 背景几个月前看到有文章介绍俄罗斯的 Hammertoss 恶意软件,使用 Twitter 作为 C&amp;C 服务。以类似方式滥用 TechNet 的也有过报道【1】。脑洞了一下觉得,使用图片(或者其他格式)作为隐写(steganography)的载体来携带 C&amp;C 控制命令更为隐蔽一些,而且携带的信息容量相对 twitter 的 ..._github c&c

springboot2.0集成activiti6.0-程序员宅基地

文章浏览阅读3.7k次,点赞2次,收藏6次。 activiti6.0直接使用starter集成到springboot2.0时,会报异常,无法直接进行集成。所以我才用spring-activiti来集成activiti6.0.整体文件结构如下:1.pom文件依赖&lt;project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.o..._springboot2.0集成activiti6.

国家c语言1级考试题库,国家计算机二级考试 c语言 上机题库100道.docx.docx-程序员宅基地

文章浏览阅读134次。国家计算机二级考试 c语言 上机题库100道.docx1调用fun函数建立班级通讯录,记录学生的编号姓名电话,人数和信息从键盘读入,信息写到myfile5.dat的二进制文件。STYPE FILE fpFun函数先将字符串s中字符按正序存放到t串中,然后把s中字符逆序连到t后. for (i=0;idata t函数fun的功能是:将字符串的字符按逆序输出,但不改变字符串的内容。例,若字符串为..._若传送给m的值为50,则程序输出,7.11.14.21.22.28.33.35.42.44.49,n=11

罗森伯格成功助力安徽省滁州市公安局110指挥中心项目-程序员宅基地

文章浏览阅读183次。安徽省滁州市公安局110指挥中心大楼(含附楼)建筑面积约60000平方米,大楼主要包括指挥中心技术用房、刑侦业务用房、特巡警用房、射击靶场、×××服务大厅、民警训练场、餐厅等,场地景观及附属建筑。建筑主体以办公为主,同时在主体大楼内也规划了公安体系数据中心。 作为整个IT/弱电系统的基础,综合布线系统在此项目中尤其显的重要。通过业主的严密筛...

OS_Sched 函数_os_sched.h-程序员宅基地

文章浏览阅读9.4k次,点赞4次,收藏8次。//任务调度//uCOS-II总是运行进入就绪态任务中优先级最高的那一个。确定哪个任务优先级最高,下面该哪个任务运行了的工作是//由调度器(Scheduler)完成的。任务级的调度是由函数OSSched()完成的。中断级的调度是由另一个函数OSIntExt()完//成的Scheduling。//注意:1) 这是一个uCOS-II内部函数,你不能在应用程序中使用它// 2_os_sched.h

物联网开发笔记(46)- 使用Micropython开发ESP32开发板之控制光敏传感器_esp32光敏传感器-程序员宅基地

文章浏览阅读2k次,点赞3次,收藏24次。使用Micropython开发ESP32开发板之控制光敏传感器_esp32光敏传感器

推荐文章

热门文章

相关标签