zoukankan      html  css  js  c++  java
  • 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 
    ");
            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!
    ");
           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
    ");
             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
    ", 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;
    }

    添加后的图片效果如下:

  • 相关阅读:
    强连通分量 Tarjan
    【二叉搜索树】hdu 3791
    【二叉树】hdu 1622 Trees on the level
    【二叉树】hdu 1710 Binary Tree Traversals
    【leetcode】lower_bound
    【leetcode dp】629. K Inverse Pairs Array
    【leetcode最短路】818. Race Car
    【leetcode 字符串】466. Count The Repetitions
    【leetcode dp】132. Palindrome Partitioning II
    【leetcode dp】Dungeon Game
  • 原文地址:https://www.cnblogs.com/streammm/p/6599241.html
Copyright © 2011-2022 走看看