jpeg exif
公司项目需要在jpeg图片里面添加exif信息,同事完成了这部分代码;但是有些手机兼容性有问题;
libexif 地址:http://libexif.sourceforge.net/
注意相关资料来之:
http://blog.csdn.net/fioletfly/article/details/53605959
注意使用的工具为:PowerExif.exe,因为项目太多了,需要对比添加~有工具可以比较好的参考.
手机兼容有问题,注意是因为一些项目没按照exif标准来添加;按标准来添加,添加后用PowerExif.exe解析,如果每项都正常了,基本手机解析不会有问题;
代码如下:
1.前面代码来至src sample下面的;
2.添加了一些必要的exif信息;
3.添加到结果如最后.
static const unsigned char exif_header[] = { 0xff, 0xd8, 0xff, 0xe1, }; /* length of data in exif_header */ static const unsigned int exif_header_len = sizeof(exif_header); /* length of data in image_jpg */ static const unsigned int image_jpg_len ;//= sizeof(image_jpg); /* start of JPEG image data section */ static const unsigned int image_data_offset = 20; #define image_data_len (image_jpg_len - image_data_offset) const char *pucMaker = "xx公司"; const char *pucModel = "拍照设备"; /* 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(); assert(mem != NULL); /* catch an out of memory condition */ /* Create a new ExifEntry using our allocator */ entry = exif_entry_new_mem (mem); assert(entry != NULL); /* Allocate memory to use for holding the tag data */ buf = exif_mem_alloc(mem, len); assert(buf != NULL); /* 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; } //需要参考PowerExif.exe软件打开图片 //添加对应的只需要对应的代码ID,exifname、数据类型、和数据长度; int cdr_write_exif_to_jpg(char *pSrcFileName, GPS_INFO sGpsInfo) { int rc = 1; char GPSversionid[5]={0x02,0x02,0x00,0x00,0x00}; FILE *f = NULL; unsigned char *exif_data; unsigned int exif_data_len; FILE *f2 = fopen(pSrcFileName, "r"); if (!f2) { fprintf(stderr, "Error creating file \n"); return -1; } fseek (f2, 0, SEEK_END); ///将文件指针移动文件结尾 int iFileSize = ftell (f2); ///求出当前文件指针距离文件开始的字节数 fseek (f2, 0, SEEK_SET); char *buf = calloc(iFileSize,sizeof(char)); if(buf == NULL){ printf("calloc fails!\n"); fclose(f2); return -1; } int i = 0; int pos = 0; char temp = 0; for(i=0; i<iFileSize-1; i++) { temp = fgetc(f2); if(EOF == temp) break; buf[pos++] = temp; } buf[pos] = 0; fclose(f2); ExifEntry *entry = NULL; ExifData *exif = exif_data_new(); if (!exif) { fprintf(stderr, "Out of memory\n"); free(buf); buf=NULL; return 2; } /* Set the image options */ exif_data_set_option(exif, EXIF_DATA_OPTION_FOLLOW_SPECIFICATION); exif_data_set_data_type(exif, EXIF_DATA_TYPE_COMPRESSED); exif_data_set_byte_order(exif, FILE_BYTE_ORDER); /* Create the mandatory EXIF fields with default data */ //exif_data_fix(exif); entry = create_tag(exif, EXIF_IFD_GPS, EXIF_TAG_GPS_VERSION_ID,4); /* Write the special header needed for a comment tag */ entry->format = EXIF_FORMAT_BYTE; entry->components = 4; exif_set_sshort(entry->data, FILE_BYTE_ORDER, GPSversionid[0]); exif_set_sshort(entry->data+1, FILE_BYTE_ORDER, GPSversionid[1]); exif_set_sshort(entry->data+2, FILE_BYTE_ORDER, GPSversionid[2]); exif_set_sshort(entry->data+3, FILE_BYTE_ORDER, GPSversionid[3]); entry = create_tag(exif, EXIF_IFD_GPS, EXIF_TAG_GPS_LATITUDE_REF,2); entry->format = EXIF_FORMAT_ASCII; memcpy(entry->data, "N", 2); ExifRational a; ExifRational b; ExifRational c; a.numerator = sGpsInfo.latitude_Degree;//纬度 a.denominator = 1; b.numerator = sGpsInfo.latitude_Cent; b.denominator = 1; c.numerator = sGpsInfo.latitude_Second; c.denominator = 1; entry = create_tag(exif, EXIF_IFD_GPS, EXIF_TAG_GPS_LATITUDE,24); entry->format = EXIF_FORMAT_RATIONAL; entry->components = 3; exif_set_rational(entry->data,FILE_BYTE_ORDER,a); exif_set_rational(entry->data+8,FILE_BYTE_ORDER,b); exif_set_rational(entry->data+16,FILE_BYTE_ORDER,c); entry = create_tag(exif, EXIF_IFD_GPS, EXIF_TAG_GPS_LONGITUDE_REF,2); entry->format = EXIF_FORMAT_ASCII; entry->components = 2; memcpy(entry->data, "E", 2); a.numerator = sGpsInfo.longitude_Degree; a.denominator = 1; b.numerator = sGpsInfo.longitude_Cent; b.denominator = 1; c.numerator = sGpsInfo.longitude_Second; c.denominator = 1; entry = create_tag(exif, EXIF_IFD_GPS, EXIF_TAG_GPS_LONGITUDE,24); entry->format = EXIF_FORMAT_RATIONAL; entry->components = 3; exif_set_rational(entry->data,FILE_BYTE_ORDER,a); exif_set_rational(entry->data+8,FILE_BYTE_ORDER,b); exif_set_rational(entry->data+16,FILE_BYTE_ORDER,c); //GPS速度单位K KM/H entry = create_tag(exif, EXIF_IFD_GPS, EXIF_TAG_GPS_SPEED_REF,2); entry->format = EXIF_FORMAT_ASCII; //entry->components = 1; memcpy(entry->data, "K", 2); //GPS速度值. entry = create_tag(exif, EXIF_IFD_GPS, EXIF_TAG_GPS_SPEED,8); entry->format = EXIF_FORMAT_RATIONAL; entry->components = 1; a.numerator = sGpsInfo.speed; a.denominator = 1; exif_set_rational(entry->data,FILE_BYTE_ORDER,a); /*date time*/ entry = create_tag(exif, EXIF_IFD_EXIF, EXIF_TAG_DATE_TIME_ORIGINAL,20); entry->format = EXIF_FORMAT_ASCII; //entry->components = 20; char pDataTime[21] = {0}; sprintf(pDataTime,"%04d-%02d-%02d %02d:%02d:%02d",sGpsInfo.D.year,sGpsInfo.D.month,sGpsInfo.D.day, sGpsInfo.D.hour,sGpsInfo.D.minute,sGpsInfo.D.second); memcpy(entry->data,pDataTime,20); //厂商信息和设备信息 entry = create_tag(exif, EXIF_IFD_0, EXIF_TAG_MAKE,strlen(pucMaker)+1); entry->format = EXIF_FORMAT_ASCII; memcpy(entry->data,pucMaker,strlen(pucMaker)); entry = create_tag(exif, EXIF_IFD_0, EXIF_TAG_MODEL,strlen(pucModel)+1); entry->format = EXIF_FORMAT_ASCII; memcpy(entry->data,pucModel,strlen(pucModel)); exif_data_save_data(exif, &exif_data, &exif_data_len); assert(exif_data != NULL); f = fopen(pSrcFileName, "wb");//write exif to this file pSrcFileName if (!f) { exif_data_unref(exif); free(buf); buf=NULL; return rc; } /* Write EXIF header */ if (fwrite(exif_header, exif_header_len, 1, f) != 1) { goto errout; } /* Write EXIF block length in big-endian order */ if (fputc((exif_data_len+2) >> 8, f) < 0) { goto errout; } if (fputc((exif_data_len+2) & 0xff, f) < 0) { goto errout; } /* Write EXIF data block */ if (fwrite(exif_data, exif_data_len, 1, f) != 1) { goto errout; } int image_data_len2 = iFileSize - image_data_offset; /* Write JPEG image data, skipping the non-EXIF header */ if (fwrite(buf+image_data_offset, image_data_len2, 1, f) != 1) { goto errout; } rc = 0; free(buf); buf = NULL; fflush(f); errout: if (fclose(f)) { fprintf(stderr, "Error writing to file %s\n", FILE_NAME); rc = 1; } /* The allocator we're using for ExifData is the standard one, so use * it directly to free this pointer. */ free(exif_data); exif_data_unref(exif); return rc; }
添加后的图片效果如下: