- A+
这里简单介绍一下如何通过开源C++工具包Exiv2读取图片中的属性信息
其实做这项工作之前也想偷懒百度一下的,大都是Java写的安卓的 ExifInterface
类,这和我的工作扯不上一点关系啊,最后终于谷歌出了Exiv2开源C++库
一、简介
Exif(Exchangeable image file format)即可交换图像文件格式,是专门为数码相机的照片设定的,可以记录数码照片的属性信息和拍摄数据。
Exif最初由日本电子工业发展协会在1996年制定,版本为1.0。1998年,升级到2.1,增加了对音频文件的支持。2002年3月,发表了2.2版。
Exif可以附加于JPEG、TIFF、RIFF等文件之中,为其增加有关数码相机拍摄信息的内容和索引图或图像处理软件的版本信息。
Windows 7操作系统具备对Exif的原生支持,通过鼠标右键点击图片打开菜单,点击属性并切换到详细信息标签下即可直接查看Exif信息。
Exif信息是可以被任意编辑的,因此只有参考的功能。
下表列出几项Exif会提供的消息,只是部分
项目 | 信息(举例) |
---|---|
制造厂商 | Canon |
相机型号 | Canon EOS-1Ds Mark III |
图象方向 | 正常(upper-left) |
图象分辨率X | 300 |
图象分辨率Y | 300 |
分辨率单位 | dpi |
Software | Adobe Photoshop CS Macintosh |
最后异动时间 | 2005:10:06 12:53:19 |
YCbCrPositioning | 2 |
曝光时间 | 0.00800 (1/125) sec |
光圈值 | F22 |
拍摄模式 | 光圈优先 |
ISO感光值 | 100 |
Exif信息版本 | 30,32,32,31 |
图象拍摄时间 | 2005:09:25 15:00:18 |
图象存入时间 | 2005:09:25 15:00:18 |
曝光补偿(EV+-) | 0 |
测光模式 | 点测光(Spot) |
闪光灯 | 关闭 |
镜头实体焦长 | 12 mm |
Flashpix版本 | 30,31,30,30 |
图象色域空间 | sRGB |
图象尺寸X | 5616 pixel |
图象尺寸Y | 3744 pixel |
二、Exif信息解析(摘自http://blog.csdn.net/fioletfly/article/details/53605959)
实例分析:PICT0021.JPG
00 FF D8 FF E1 3A 59 45 78 69 66 00 00 4D 4D 00 2A
10 00 00 00 08 00 0C 01 0E 00 02 00 00 00 0E 00 00
20 03 F4 01 0F 00 02 00 00 00 20 00 00 04 02 01 10
30 00 02 00 00 00 20 00 00 04 22 01 12 00 03 00 00
40 00 01 00 01 00 00 01 1A 00 05 00 00 00 01 00 00
50 04 42 01 1B 00 05 00 00 00 01 00 00 04 4A 01 28
60 00 03 00 00 00 01 00 02 00 00 01 31 00 02 00 00
70 00 20 00 00 04 52 01 32 00 02 00 00 00 14 00 00
80 04 72 02 13 00 03 00 00 00 01 00 01 00 00 87 69
90 00 04 00 00 00 01 00 00 00 9E 88 25 00 04 00 00
A0 00 01 00 00 02 A2 00 00 02 E4 00 28 82 9A 00 05
B0 00 00 00 01 00 00 04 86 82 9D 00 05 00 00 00 01
C0 00 00 04 8E 88 22 00 03 00 00 00 01 00 02 00 00
D0 88 27 00 03 00 00 00 01 00 C8 00 00 90 00 00 07
E0 00 00 00 04 30 32 32 31 90 03 00 02 00 00 00 14
F0 00 00 04 96 90 04 00 02 00 00 00 14 00 00 04 AA
100 91 01 00 07 00 00 00 04 01 02 03 00 91 02 00 05
110 00 00 00 01 00 00 04 BE 92 01 00 0A 00 00 00 01
120 00 00 04 C6 92 02 00 05 00 00 00 01 00 00 04 CE
130 92 04 00 0A 00 00 00 01 00 00 04 D6 92 05 00 05
140 00 00 00 01 00 00 04 DE 92 06 00 05 00 00 00 01
150 00 00 04 E6 92 07 00 03 00 00 00 01 00 02 00 00
160 92 08 00 03 00 00 00 01 00 00 00 00 92 09 00 03
170 00 00 00 01 00 20 00 00 92 0A 00 05 00 00 00 01
180 00 00 04 EE 92 7C 00 07 00 00 00 40 00 00 04 F6
190 A0 00 00 07 00 00 00 04 30 31 30 30 A0 01 00 03
1A0 00 00 00 01 00 01 00 00 A0 02 00 04 00 00 00 01
1B0 00 00 12 00 A0 03 00 04 00 00 00 01 00 00 0D 80
1C0 A0 05 00 04 00 00 00 01 00 00 02 84 A2 15 00 05
1D0 00 00 00 01 00 00 05 36 A2 17 00 03 00 00 00 01
1E0 00 02 00 00 A3 00 00 07 00 00 00 01 03 00 00 00
1F0 A3 01 00 07 00 00 00 01 01 00 00 00 A4 01 00 03
200 00 00 00 01 00 00 00 00 A4 02 00 03 00 00 00 01
210 00 00 00 00 A4 03 00 03 00 00 00 01 00 00 00 00
220 A4 04 00 05 00 00 00 01 00 00 05 3E A4 05 00 03
230 00 00 00 01 00 29 00 00 A4 06 00 03 00 00 00 01
240 00 00 00 00 A4 07 00 03 00 00 00 01 00 00 00 00
250 A4 08 00 03 00 00 00 01 00 00 00 00 A4 09 00 03
260 00 00 00 01 00 00 00 00 A4 0A 00 03 00 00 00 01
270 00 00 00 00 A4 0B 00 07 00 00 00 04 00 00 00 00
280 A4 0C 00 03 00 00 00 01 00 00 00 00 00 00 00 00
290 00 02 00 01 00 02 00 00 00 04 52 39 38 00 00 02
2A0 00 07 00 00 00 04 30 31 30 30 00 00 00 00 00 05
2B0 00 00 00 01 00 00 00 04 02 02 00 00 00 01 00 02
2C0 00 00 00 02 4E 00 00 00 00 02 00 05 00 00 00 03
2D0 00 00 05 46 00 03 00 02 00 00 00 02 45 00 00 00
2E0 00 04 00 05 00 00 00 03 00 00 05 5E 00 00 00 00
2F0 00 06 01 03 00 03 00 00 00 01 00 06 00 00 01 1A
300 00 05 00 00 00 01 00 00 05 76 01 1B 00 05 00 00
310 00 01 00 00 05 7E 01 28 00 03 00 00 00 01 00 02
320 00 00 02 01 00 04 00 00 00 01 00 00 07 F4 02 02
330 00 04 00 00 00 01 00 00 32 5D 00 00 00 00 00 00
FF D8 SOI
FF E1 APP1
3A 59 APP1 LENGTH
45 78 69 66 00 00 Exif ASCII结束符两个
4D 4D MM big endian TIFF Header (注意小端的为:49492A00 08000000)
00 2A fixed
00 00 00 08 IFD0 offset
00 0C IFD0: number of TAGs 12个tag,每个12字节。
01 0E TAG Image title
00 02 TYPE ASCII
00 00 00 0E count 最多13个字符
00 00 03 F4 offset +0C=0x400 可以看到DCIM\100MEDIA (0x0c from the start of the TIFF header 4D4D MM)
01 0F TAG Image input equipment manuf
00 02 TYPE ASCII
00 00 00 20 count 最多31个字符
00 00 04 02 offset +0c=0x040E 可以看到TCL
01 10 TAG Image input equipment model
00 02 TYPE ASCII
00 00 00 20 count
00 00 04 22 offset +0c=0x042E 可以看到SDV05
01 12 TAG Orientation of image
00 03 SHORT 00 01
00 00 00 01 count
00 01 00 00 value
01 1A TAG Image resolution in width 0x0442+0c=0x44E,可以看到00 00 00 48/00 00 00 01
00 05 RATIONAL
00 00 00 01 count
00 00 04 42 offset +0c=0x44E,可以看到00 00 00 48/00 00 00 01
01 1B TAG Image resolution in height
00 05 RATIONAL
00 00 00 01
00 00 04 4A offset+0c=0x456 可以看到00 00 00 48/00 00 00 01
01 28 Unit of X and Y resolution
00 03 SHORT 00 02
00 00 00 01
00 02 00 00
01 31 Software used
00 02 ASCII
00 00 00 20 count
00 00 04 52 offset +0c =0x45E 可以看到0.0.2
01 32 DateTime
00 02 ASCII
00 00 00 14 20字节
00 00 04 72 offset+0c=0x47E,可以看到2012:07:29 21:28:18
02 13 YCbCrPositioning
00 03 SHORT 00 01
00 00 00 01
00 01 00 00
87 69 Exif IFD Pointer
00 04 LONG
00 00 00 01 count
00 00 00 9E offset+0c=0xAA
88 25 GPS Info IFD Pointer
00 04 LONG
00 00 00 01 count
00 00 02 A2 offset+0c=0x02AE
00 00 02 E4 nextIFD IFD1 offset
00 28 Exif IFD number of TAGs
82 9A ExposureTime
00 05 RATIONAL
00 00 00 01 count
00 00 04 86 offset+0c=0x0492
...
Exif的相关信息这里先不做分析,请大家参照上面的文档自己分析了。
这里主要是分析GPS相关信息
GPS Info IFD Pointer 0x02AE 从上面数据2A0行的后面看数据
00 05 count of TAGs
00 00 GPSVersionID
00 01 BYTE
00 00 00 04 count
02 02 00 00 value 2.2.0.0
00 01 GPSLatitudeRef
00 02 ASCII
00 00 00 02 count
4E 00 00 00 N North
00 02 GPSLatitude
00 05 RATIONAL 前4字节为分子,后4字节为分母,十六进制先转为十进制
00 00 00 03 count
00 00 05 46 offset+0c=0x552 16 00 00 00 01 00 00 00 22 00 00 00 01 00 00 00 51 00 00 00 04 00 00 00
22/1=22 34/1=34 81/4= 20.25
通过windows的右键属性看详细信息:22;34;20.249999999999915
00 03 GPSLongitudeRef
00 02
00 00 00 02 count
45 00 00 00 East
00 04 GPSLongitude
00 05 RATIONAL
00 00 00 03 count
00 00 05 5E offset+0c=0x56A 71 00 00 00 01 00 00 00 37 00 00 00 01 00 00 00 6C 00 00 00 04 00
113/1=113 55/1=55 108/4=27
通过windows的右键属性看详细信息:113;55;27.000000000000171
550 04 00 16 00 00 00 01 00 00 00 22 00 00 00 01 00
560 00 00 51 00 00 00 04 00 00 00 71 00 00 00 01 00
570 00 00 37 00 00 00 01 00 00 00 6C 00 00 00 04 00
580 00 00 00 00 00 48 00 00 00 01 00 00 00 48 00 00
590 00 01 00 00 00 00 00 00
上面的分析知识帮助理解Exif文件在图片中的存储协议,加深印象,这个在我的实际操作中并未使用(因为我也不晓得作者是怎么把图片解码成这样的)
三、应用Exiv2工具包(下载地址)
刚开始我实在Windows7+VS2013环境下使用的,但是在添加路径读取图片的时候始终不能成功,现在想来应该是动态链接库等各种配置没有搞定,后来就老老实实的切到了ubuntu+Qt下,修改了一下examples,终于成功了(也算能给老师交差了)
在ubuntu下,文件包的结构是这样的
dist/linux/bin/exiv2 exiv2 and sample applications
dist/linux/lib/libexiv2.so.26.0.0 shared library
dist/linux/include/exiv2/ include files
dist/linux/share/ man pages
dist/samples/ sample code
dist/logs/ log files
dist/contrib/Qt Qt code and notes
要运行exiv2库,在终端下执行
$ cd dist$ export LD_LIBRARY_PATH="$PWD/linux/lib:$LD_LIBRARY_PATH"$ linux/bin/exiv2To compile and link your own code:$ cd dist$ sudo cp -R linux/* /usr/local/$ g++ -std=c++98 samples/exifprint.cpp -L/usr/local/lib -lexiv2 -o exifprint$ ./exifprint --versionexiv2=0.26.0...xmlns=xmpidq:http://ns.adobe.com/xmp/Identifier/qual/1.0/$
显示如上就算是完成安装完成了,然后新建一个控制台工程,把刚才的共享库等包含在工程的配置文件中,参考examples或者下载的解压包中的samples文件夹中的例程,修修改改,基本上就满足我的需求了
在Exiv2库中,可以读写的属性信息参考此链接
效果图,以GPS信息为例,这是windows7下右键属性读到的信息
这是利用Exiv2读到的
filepath--想要读取的图片的路径
exifDataName--此链接中的Key值
代码方法1
std::string getValueOfTag1(std::string filepath, std::string &exifDataName){Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(filepath);if(image.get() == 0)cout<<"failed to opened..."<<endl;image->readMetadata();Exiv2::ExifData &exifData = image->exifData();if (exifData.empty()) {std::cout<<"empty......"<<endl;}Exiv2::Exifdatum& Modle_tag = exifData[exifDataName];std::string valueOfTag = Modle_tag.toString();std::cout<<exifDataName<<" is "<<valueOfTag<<std::endl;return valueOfTag;}
方法2
std::string getValueOfTag2(std::string filepath, std::string &exifDataName)
{Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(filepath);if(image.get() == 0)cout<<"failed to opened..."<<endl;image->readMetadata();Exiv2::ExifData &exifData = image->exifData();if (exifData.empty()) {std::cout<<"empty......"<<endl;}Exiv2::ExifKey key(exifDataName);Exiv2::ExifData::const_iterator i = exifData.findKey(key);std::cout << "key is "<< i->key() <<std::endl;//the name of key// std::cout << "Tag(hex) is "<< "0x" << std::hex << i->tag() << std::endl;// std::cout << "Type is "<< i->typeName() << std::endl;// std::cout << "Tag(dec) is "<< std::dec << i->count() <<std::endl;// std::cout << "Value of tag is "<< std::dec << i->value()<<std::endl;std::cout << "Value of tag is "<< i->value()<<std::endl;string valueOfTag = "yeah!";return valueOfTag;}
使用时只需要在main中直接调用这其中一个函数即可,注意图片的路径!
四、小结
该库可供读写的选项十分丰富,但是也存在不足(也可能时个人原因)。比如在获取信息的GPS数据的精度问题上,只能够保留四个小数位,误差太大,误差还是很大的,略有不足,但是镜头焦距上,有更高的准确度。如果朋友们能够读取更高精度的GPS信息,请告知一下,谢谢~
相关链接:
http://www.exiv2.org/download.html
exif信息查询:
https://exif.tuchong.com/
- 我的微信
- 这是我的微信扫一扫
- 我的微信公众号
- 我的微信公众号扫一扫