/* Some utility functions for exifs. */ #include #include #include #include "exif.h" /* Reads an int32 with the specified endianness from buf */ static int32_t readint32(uint8_t *buf,int littleendian) { if (!littleendian) return buf[0]+(buf[1]<<8)+(buf[2]<<16)+(buf[3]<<24); else return buf[3]+(buf[2]<<8)+(buf[1]<<16)+(buf[0]<<24); } /* Reads an int16 with the specified endianness from buf */ static int16_t readint16(uint8_t *buf,int littleendian) { if (!littleendian) return buf[0]+(buf[1]<<8); else return (buf[1]<<16)+(buf[0]<<24); } /* Get a field form the tiff directory ifd */ static int getdirent(uint8_t taghi,uint8_t taglo,ifd_t *ifd,int littlendian, int32_t *data,int32_t *ncomp) { int i; int16_t tag; if (!littlendian) tag = (taghi<<8)+taglo; else tag = (taglo<<8)+taghi; for (i=0;inumentry;i++) { if (ifd->dir[i].tag==tag) { *data = readint32((uint8_t*)(&(ifd->dir[i].data)),littlendian); *ncomp = readint32((uint8_t*)(&(ifd->dir[i].ncomp)),littlendian); return 0; } } return -1; } /* Scan for 0xffe1 bigendian in the first giveupafter bytes of buf */ static uint8_t *find_app1(uint8_t *buf,int giveupafter) { uint8_t *cp=buf; while (cpnumentry = readint16(data,prop->endian); ifd->dir = (tiffdir_t*)(data+2); ifd->next = (ifd_t*)readint32(data+ifd->numentry*sizeof(tiffdir_t)+2, prop->endian); return ifd; } /* Gets all the ifds (this nextifd business is a little haphazard...) */ static int getifds(exif_properties_t *prop) { ifd_t *curifd,*nextifd; prop->ifd = getifd(prop->tiffbase+readint32(prop->tiffbase+4,prop->endian), prop); curifd = prop->ifd; while (curifd->next) { nextifd = (ifd_t*)getifd(prop->tiffbase+(size_t)curifd->next,prop); curifd->next = nextifd; curifd = nextifd; } return 0; } /* Tries to get the exif ifd */ static int getexififd(exif_properties_t *prop) { int32_t exifofs,dummy; if (getdirent(TH_EXIF_OFFSET,prop->ifd,prop->endian,&exifofs,&dummy)) return -1; prop->exif_ifd = getifd(prop->tiffbase+exifofs,prop); return 0; } /* fill out the exif properties structure prop based on data in buf with the app1 marker in the first giveupafter bytes */ int exif_get_properties(uint8_t *buf,int giveupafter,exif_properties_t *prop) { if (!(prop->start=find_app1(buf,giveupafter))) return -1; /* length should be big-endian */ prop->length = (int)(prop->start[0])+(int)(prop->start[1])*256-2; if (((int16_t*)(prop->start))[4]==0x4d4d) prop->endian = 1; else if (((int16_t*)(prop->start))[4]==0x4949) prop->endian = 0; else return -1; prop->tiffbase = prop->start+8; getifds(prop); getexififd(prop); return 0; } static void release_ifds(ifd_t *theifd) { if (theifd->next) { release_ifds(theifd->next); free(theifd->next); } } /* Free RAM allocated by get_properties and invalidate structure */ int exif_release_properties(exif_properties_t *prop) { release_ifds(prop->ifd); free(prop->exif_ifd); prop->exif_ifd = NULL; prop->ifd = NULL; prop->start = NULL; prop->length = 0; prop->tiffbase = NULL; return 0; } int exif_get_tagval(uint8_t taghi,uint8_t taglo,exif_properties_t *prop, int32_t *data,int32_t *ncomp,int ifdsel) { ifd_t *ifd; int ifdno=1; if (ifdsel==-1) return getdirent(taghi,taglo,prop->exif_ifd,prop->endian,data,ncomp); else if (ifdsel==0) { if (!getdirent(taghi,taglo,prop->exif_ifd,prop->endian,data,ncomp)) return 0; ifd = prop->ifd; while (ifd) { if (!getdirent(taghi,taglo,prop->exif_ifd,prop->endian,data,ncomp)) return 0; ifd = ifd->next; } return -1; } else { ifd = prop->ifd; while (ifd&&ifdno!=ifdsel) { ifd = ifd->next; ifdno++; } if (ifdno!=ifdsel) return -1; return getdirent(taghi,taglo,prop->exif_ifd,prop->endian,data,ncomp); } return -1; } char *exif_get_string(uint8_t taghi,uint8_t taglo,exif_properties_t *prop) { int32_t data,ncomp; char *str=NULL,*sp; int i; if (!exif_get_tagval(taghi,taglo,prop,&data,&ncomp,0)) { str = (char*)malloc((ncomp+1)*sizeof(char)); if (!str) return str; sp = (char*)prop->tiffbase+data; for (i=0;itiffbase+data,prop->endian); denom = readint32(prop->tiffbase+data+sizeof(int32_t),prop->endian); res = (double)numer/denom; } return res; } #if 0 int main(int argc,char **argv) { FILE *einf; uint8_t buf[0x1000]; exif_properties_t prop; char *cp; int32_t data,dummy; double cbpp; einf = fopen(argv[1],"r"); fread(buf,1,0x1000,einf); fclose(einf); if (exif_get_properties(buf,200,&prop)) { printf("failed\n"); exit(-1); } if ((cp = exif_get_string(EXIF_DATETIMEORIGINAL,&prop))) { printf("%s\n",cp); free(cp); } else printf("Entry not found\n"); cbpp = exif_get_rational(EXIF_COMPRESSEDBITSPERPIXEL,&prop); printf("%f\n",cbpp); if (!exif_get_tagval(TH_COMPRESSION,&prop,&data,&dummy,0)) printf("FL: %x\n",data); else printf("FL not found\n"); exif_release_properties(&prop); return 0; } #endif /* vi: ts=2 */