wiki上有EXIF的介绍,不抄了 http://zh.wikipedia.org/wiki/EXIF
分析exif数据的c库有libexif, c++库有exiv2。exiv2比libexif支持更多格式,最近更新也比较活跃。这里简单介绍下如何使用libexif
libexif主要的数据结构有ExifData, ExifContent, ExifEntry
ExifData
包含了所有的exif数据,可以简单地用exif_data_new_from_file(const char* path)来创建,其内部使用ExifLoader. 也可以new一个loader手动载入然后取出ExifData.
ExifContent
包含了单个IFD的所有tag,可以用 exif_data_foreach_contetn()来遍历操作ExifData中的ExifContent,用exif_content_get_ifd来读取一个content所属的ifd
ifd有如下值
EXIF_IFD_0
EXIF_IFD_1
EXIF_IFD_EXIF
EXIF_IFD_GPS
EXIF_IFD_INTEROPERABILITY
EXIF_IFD_COUNT
ifd可以用exif_ifd_get_name(ExifIfd ifd)来把枚举转换成相应的名字
ExifEntry
保存了一个tag的信息,ExifContent提供了一个函数来提取ExifEntry
exif_content_get_entry(ExifContent*, ExifTag)
同时,ExifData提供了一个宏来提取ExifEntry,其实就是对每个ifd逐个调用exif_content_get_entry
#define exif_data_get_entry(d,t) \
(exif_content_get_entry(d->ifd[EXIF_IFD_0],t) ? \
exif_content_get_entry(d->ifd[EXIF_IFD_0],t) : \
exif_content_get_entry(d->ifd[EXIF_IFD_1],t) ? \
exif_content_get_entry(d->ifd[EXIF_IFD_1],t) : \
exif_content_get_entry(d->ifd[EXIF_IFD_EXIF],t) ? \
exif_content_get_entry(d->ifd[EXIF_IFD_EXIF],t) : \
exif_content_get_entry(d->ifd[EXIF_IFD_GPS],t) ? \
exif_content_get_entry(d->ifd[EXIF_IFD_GPS],t) : \
exif_content_get_entry(d->ifd[EXIF_IFD_INTEROPERABILITY],t) ? \
exif_content_get_entry(d->ifd[EXIF_IFD_INTEROPERABILITY],t) : NULL)
有了ExifEntry,我们就可以读取tag的信息了。ExifEntry有个ExifTag的数据成员tag,获取tag信息主要的几个函数有
const char* exif_tag_get_title_in_ifd(ExifTag, ExifIfd)
const char* exif_entry_get_value(ExifEntry* entry, char* val, unsigned int maxlen)
有了这些就可以写个小程序来读取照片的exif信息了
#include <cstdio>
#include <cstring>
#include <libexif/exif-data.h>
void read_exif_entry(ExifEntry *ee, void* ifd)
{
char v[1024];
// strncpy(t, exif_tag_get_title_in_ifd(ee->tag, exif_entry_get_ifd(ee)), sizeof(t));
// strncpy(t, exif_tag_get_title_in_ifd(ee->tag, *((ExifIfd*)ifd)), sizeof(t));
//trim t
printf("%s: %s\n"
// , exif_tag_get_name_in_ifd(ee->tag, *((ExifIfd*)ifd))
, exif_tag_get_title_in_ifd(ee->tag, *((ExifIfd*)ifd))
// , exif_tag_get_description_in_ifd(ee->tag, *((ExifIfd*)ifd))
, exif_entry_get_value(ee, v, sizeof(v)));
}
void read_exif_content(ExifContent *ec, void *user_data)
{
ExifIfd ifd = exif_content_get_ifd(ec);
if (ifd == EXIF_IFD_COUNT)
fprintf(stderr, "exif_content_get_ifd error");
printf("======IFD: %d %s======\n", ifd, exif_ifd_get_name(ifd));
exif_content_foreach_entry(ec, read_exif_entry, &ifd);
}
int main(int argc, char** argv)
{
ExifData* ed = exif_data_new_from_file(argv[1]);
if (!ed) {
fprintf(stderr, "An error occur");
return 1;
}
//exif_data_set_option(ed,
exif_data_foreach_content(ed, read_exif_content, NULL);
exif_data_unref(ed);
return 0;
}