Use the libexif open source library to modify the exif information of jpeg photos
Introduction to libexif
libexif is an open source image exif information operation library, which provides a common operation interface for exif information;
exif is the auxiliary information in the photo, and the common exif information is shown in the figure:
1. Read exif information
Use libexif to traverse exif information, refer to: https://blog.csdn.net/ibingow/article/details/7724453
2. Write exif information
illustrate
The code for writing exif refers to the code of a big guy in stackoverflow:
His code uses two libraries, libjpeg and libexif, and encapsulates some more interfaces. You can directly set some exif information, all in JpegEncoderEXIF.c
:
Example: Modify the GPS altitude in exif
In the above code, there is no interface for directly modifying exif. The following is a demo for modifying the altitude. The final effect:
implementation code (Linux C):
//linux eclipse环境
#include <stdio.h>
#include <stdlib.h>
#include <libexif/exif-data.h>
#include <libjpeg/jpeg-data.h>
#include <JpegEncoderEXIF/JpegEncoderEXIF.h>
/*
* create_tag() is from the write-exif.c sample code that is floating
* around the interweb - with thanks to whoever created it!
*/
/* Create a brand-new tag with a data field of the given length, in the
* given IFD. This is needed when exif_entry_initialize() isn't able to create
* this type of tag itself, or the default data length it creates isn't the
* correct length.
*/
static ExifEntry *create_tag(ExifData *exif, ExifIfd ifd, ExifTag tag, size_t len)
{
void *buf;
ExifEntry *entry;
/* Create a memory allocator to manage this ExifEntry */
ExifMem *mem = exif_mem_new_default();
/* Create a new ExifEntry using our allocator */
entry = exif_entry_new_mem (mem);
/* Allocate memory to use for holding the tag data */
buf = exif_mem_alloc(mem, len);
/* Fill in the entry */
entry->data = buf;
entry->size = len;
entry->tag = tag;
entry->components = len;
entry->format = EXIF_FORMAT_UNDEFINED;
/* Attach the ExifEntry to an IFD */
exif_content_add_entry (exif->ifd[ifd], entry);
/* The ExifMem and ExifEntry are now owned elsewhere */
exif_mem_unref(mem);
exif_entry_unref(entry);
return entry;
}
int main(int argc, char *argv[])
{
if(argc < 3){
fprintf(stderr, "Usage: %s <src.jpg> <out.jpg>\n", argv[0]);
return -1;
}
//1.获取jpeg、exif数据
JPEGData *pJpegData = jpeg_data_new_from_file(argv[1]);
if(!pJpegData){
printf("jpeg_data_new_from_file err\n");
return -1;
}
ExifData *pExifData = jpeg_data_get_exif_data(pJpegData);
if(!pExifData){
printf("jpeg_data_get_exif_data err\n");
return -1;
}
//2.获取对应的entry
printf("Now to get entry!************************************\n");
//获取GPS海拔信息的entry
ExifEntry *pExifEntry = exif_content_get_entry(pExifData->ifd[EXIF_IFD_GPS], EXIF_TAG_GPS_ALTITUDE);
if(!pExifEntry){
printf("exif_content_get_entry err\n");
printf("No EXIF_TAG_GPS_ALTITUDE_REF info!\n");
return -1;
}
char value_array[1024];
printf("EXIF_TAG_GPS_LATITUDE: %s\n", exif_entry_get_value(pExifEntry, value_array, sizeof(value_array)));
ExifByteOrder byte_order = exif_data_get_byte_order(pExifData);//获取图片的字节序
ExifRational altitude = {
.denominator = 10,//分母
.numerator = 666//分子
//最终写入海拔:666/10 = 66.6m
};
exif_set_rational(pExifEntry->data, byte_order, altitude);
//写入exif到jpeg
jpeg_data_set_exif_data(pJpegData, pExifData);
//jpeg另存为
if(0 == jpeg_data_save_file(pJpegData, argv[2])){
printf("jpeg_data_save_file error!\n");
return -1;
}
return 0;
}