libexif是一个用于解析、编辑和保存EXIF数据的库。它支持EXIF 2.1标准(以及2.2中的大多数)中描述的所有EXIF标签。它是用纯C语言编写的,不需要任何额外的库。源码地址:https://github.com/libexif/libexif ,最新发布版本为0.6.24,它的license为LGPL-2.1。
EXIF全称为Exchangeable Image File format,可交换图像文件格式,是专门为数码相机的照片设定的文件格式,可以记录数码照片的属性信息和拍摄数据。EXIF可以附加于JPEG、TIFF、RIFF等文件之中,为其增加有关数码相机拍摄信息的内容和索引图或图像处理软件的版本信息。EXIF信息是可以被任意编辑的,因此只有参考的功能。
EXIF信息以0xFFE1作为开头标记,后两个字节表示EXIF信息的长度。所以EXIF信息最大为64kB,而内部采用TIFF格式。
libexif在Windows和Linux上编译过程:
从https://github.com/libexif/libexif.git clone源码,然后切换到tag v0.6.24,执行:git checkout v0.6.24
1.Linux上编译:
(1).需要先安装依赖,执行如下命令:
sudo apt install autoconf autopoint libtool
(2).编译源码,依次执行如下命令:
autoreconf -i
./configure --prefix=${PWD}/install --disable-docs
make
make install
编译完成后在install目录下,会生成include、lib、share三个目录。
2.Windows上编译:
(1).新建libexif工程,参考Linux下生成的libexif.a中的文件,将相关文件添加到工程中;
(2).将Linux下生成的config.h文件做调整并添加到libexif工程中,调整后的config.h内容如下:
/* config.h. Generated from config.h.in by configure. */
/* config.h.in. Generated from configure.ac by autoheader. */
/* Define to 1 if translation of program messages to the user's native
language is requested. */
/* #undef ENABLE_NLS */
#define GETTEXT_PACKAGE "libexif-12"
#if defined(_MSC_VER)
# pragma warning(push)
# pragma warning(disable: 4127) // warning C4127: Conditional expression is constant
#include <BaseTsd.h>
typedef SSIZE_T ssize_t;
#endif
/* Define to 1 if you have the Mac OS X function CFLocaleCopyCurrent in the
CoreFoundation framework. */
/* #undef HAVE_CFLOCALECOPYCURRENT */
/* Define to 1 if you have the Mac OS X function CFPreferencesCopyAppValue in
the CoreFoundation framework. */
/* #undef HAVE_CFPREFERENCESCOPYAPPVALUE */
/* Define if the GNU dcgettext() function is already present or preinstalled.
*/
/* #undef HAVE_DCGETTEXT */
/* Define to 1 if you have the <dlfcn.h> header file. */
/* #undef HAVE_DLFCN_H */
/* Define if the GNU gettext() function is already present or preinstalled. */
/* #undef HAVE_GETTEXT */
/* Define if you have the iconv() function and it works. */
/* #undef HAVE_ICONV */
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
/* Define to 1 if you have the `localtime_r' function. */
/* #undef HAVE_LOCALTIME_R */
/* Define to 1 if you have localtime_s() */
#define HAVE_LOCALTIME_S 1
/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1
/* Define to 1 if you have the <stdio.h> header file. */
#define HAVE_STDIO_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
/* Define to 1 if you have the <strings.h> header file. */
/* #undef HAVE_STRINGS_H */
/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <unistd.h> header file. */
/* #undef HAVE_UNISTD_H */
/* Define as const if the declaration of iconv() needs const. */
/* #undef ICONV_CONST */
/* Define to the sub-directory where libtool stores uninstalled libraries. */
//#define LT_OBJDIR ".libs/"
/* Name of package */
#define PACKAGE "libexif"
/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT "libexif-devel@lists.sourceforge.net"
/* Define to the full name of this package. */
#define PACKAGE_NAME "EXIF library"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "EXIF library 0.6.24"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "libexif"
/* Define to the home page for this package. */
#define PACKAGE_URL "https://libexif.github.io/"
/* Define to the version of this package. */
#define PACKAGE_VERSION "0.6.24"
/* Define to 1 if all of the C90 standard headers exist (not just the ones
required in a freestanding environment). This macro is provided for
backward compatibility; new code need not use it. */
#define STDC_HEADERS 1
/* Version number of package */
#define VERSION "0.6.24"
/* Number of bits in a file offset, on hosts where this is settable. */
/* #undef _FILE_OFFSET_BITS */
/* Define for large files, on AIX-style hosts. */
/* #undef _LARGE_FILES */
/* Define to `__inline__' or `__inline' if that's what the C compiler
calls it, or to nothing if 'inline' is not supported under any name. */
#ifndef __cplusplus
/* #undef inline */
#endif
(3).将Linux上生成的_stdint.h文件也添加到此工程中;
(4).编译工程生成libexif.lib静态库。
对带有exif信息的jpg图像生成缩略图的测试代码如下:
int test_libexif_thumbnail()
{
// reference: https://github.com/libexif/libexif/blob/master/contrib/examples/thumbnail.c
// Create an ExifLoader object to manage the EXIF loading process
ExifLoader* l = exif_loader_new();
if (!l) {
std::cerr << "Error: fail to exif_loader_new\n";
return -1;
}
#ifdef _MSC_VER
constexpr char* jpg_name{ "../../../test_images/exif.jpg" };
#else
constexpr char* jpg_name{ "test_images/exif.jpg" };
#endif
// Load the EXIF data from the image file
exif_loader_write_file(l, jpg_name);
// Get a pointer to the EXIF data
ExifData* ed = exif_loader_get_data(l);
if (!ed) {
std::cerr << "Error: fail to exif_loader_get_data\n";
return -1;
}
// The loader is no longer needed--free it
exif_loader_unref(l);
// Make sure the image had a thumbnail before trying to write it
if (ed->data && ed->size) {
std::cout << "exif data size: " << ed->size << "\n";
char thumb_name[1024];
snprintf(thumb_name, sizeof(thumb_name), "%s_thumb.jpg", jpg_name);
FILE* thumb = fopen(thumb_name, "wb");
if (!thumb) {
std::cerr << "Error: fail to fopen: " << thumb_name << "\n";
return -1;
}
// Write the thumbnail image to the file
fwrite(ed->data, 1, ed->size, thumb);
fclose(thumb);
}
exif_data_unref(ed);
return 0;
}
Windows上和Linux上的执行结果如下图所示:
GitHub:https://github.com/fengbingchun/OpenCV_Test