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;
}

 

添加后的图片效果如下:

 

posted @ 2017-03-22 12:37  码工木木  阅读(1611)  评论(1编辑  收藏  举报