#include #include #include "picoexif.h" unsigned char exif_buf[EXIF_MAXBUF]; // raw buffer for data, PUBLIC // EXIF file format: https://www.media.mit.edu/pia/Research/deepview/exif.html // EXIF tag type list: https://www.exiv2.org/tags.html // vartype type length // 0 -- // 1 uint8 1 // 2 string 1 items=number of bytes // 3 uint16 2 // 4 uint32 4 // 5 uratio 4 2 bytes for numerator, then 2 bytes for denominator // 6 sint8 1 // 7 undef 1 // 8 sint16 2 // 9 sint32 4 // 10 sratio 8 // 11 float 4 // 12 double 8 // counters and pointers int exif_itemcnt; // incremented by exif_additem, PUBLIC int exif_varbuflen; // offset from start of varbuffer, PUBLIC int exif_errno=0; // error (too many items, or insufficient varbuffer, 0 if none) // set 4-byte integer in raw buffer void exif_setlong(int offs,unsigned long v){ exif_buf[offs]=v;v>>=8; exif_buf[offs+1]=v;v>>=8; exif_buf[offs+2]=v;v>>=8; exif_buf[offs+3]=v; } unsigned long exif_getlong(int offs){ return (exif_buf[offs]<<0)+(exif_buf[offs+1]<<8)+(exif_buf[offs+2]<<16)+(exif_buf[offs+3]<<24); } // set 2-byte integer in raw buffer void exif_setint(int offs,int v){ exif_buf[offs]=v;v>>=8; exif_buf[offs+1]=v; } int exif_getint(int offs){ return (exif_buf[offs]<<0)+(exif_buf[offs+1]<<8); } // set string s in raw buffer, optionally null-terminated // returns length of string incl. null int exif_setstr(int offs,char*s,int nullterm){ int strl=0; while(s[0]){exif_buf[offs]=s[0];s++;offs++;strl++;} // copy, increment variables if(nullterm){exif_buf[offs]=0;strl++;} // null-terminate return strl; } // add string to variable-length buffer, return -1 if overflow, otherwise return raw-buffer address where it is saved to int exif_addbufstr(char*s){ if( (strlen(s)+exif_varbuflen+1) >= EXIF_MAXVARBUFLEN ) return -1; // safety check to not write more to buffer than allowed int offs=exif_varbuflen; exif_varbuflen=exif_varbuflen+exif_setstr(EXIF_BUF_VARBUFSTART+exif_varbuflen,s,1); return offs+EXIF_BUF_VARBUFSTART; } // raw buffer offset from directory record number int exif_getrecordoffs(int record){ return EXIF_INTERNAL_BUF_FIRSTDIR+EXIF_INTERNAL_ITEMLEN*record; } // for exif_subtractoffsptr() - accesss the record type, value int exif_getrecordtype(int record) { return exif_getint(exif_getrecordoffs(record)+EXIF_RECORDOFFSET_TYPE); } void exif_setrecordtype(int record,int val){ exif_setint(exif_getrecordoffs(record)+EXIF_RECORDOFFSET_TYPE,val); } long exif_getrecordval(int record) { return exif_getlong(exif_getrecordoffs(record)+EXIF_RECORDOFFSET_VAL); } void exif_setrecordval(int record,int val){ exif_setlong(exif_getrecordoffs(record)+EXIF_RECORDOFFSET_VAL,val); } //long exif_getrecordlen(int record){ return exif_getlong(exif_getrecordoffs(record)+EXIF_RECORDOFFSET_LEN); } // convert pointer values to remove the unused directory entries void exif_subtractoffsptr(){ int diff=EXIF_INTERNAL_ITEMLEN*(EXIF_MAXITEMS-exif_itemcnt); for(int t=0;t=(EXIF_MAXITEMS)){ exif_errno=EXIF_ERR_TOOMANYITEMS; #ifdef EXIF_DEBUG_PRINTERR fprintf(stderr,"ERROR: too many items, skipping\n"); #endif return; } exif_setdir(exif_itemcnt,type,vartype,items,val); exif_itemcnt++; } // user function, main API call for adding a string variable to directory array and to var-buffer, PUBLIC void exif_additemstr(int type,char*s){ if(exif_itemcnt>=(EXIF_MAXITEMS)){ exif_errno=EXIF_ERR_TOOMANYITEMS_STR; #ifdef EXIF_DEBUG_PRINTERR fprintf(stderr,"ERROR: too many items, skipping (str)\n"); #endif return; } int len=strlen(s); if(len<5){ // fits the directory item, so no var-buffer allocation unsigned long l=0; for(int t=0;t>8;exif_buf[3]=(len-2); // total length of the output, minus the two bytes of FFE1 chunk header; endianness, cannot use exif_setint() }