diff --git a/image_utils.c b/image_utils.c index 2f65caa..79eb4f8 100644 --- a/image_utils.c +++ b/image_utils.c @@ -35,6 +35,7 @@ #include #include +#include "upnpreplyparse.h" #include "image_utils.h" #include "log.h" @@ -282,6 +283,91 @@ image_get_jpeg_resolution(const char * path, int * width, int * height) return ret; } +int +image_get_jpeg_date_xmp(const char * path, char ** date) +{ + FILE *img; + unsigned char buf[8]; + char *data = NULL; + u_int16_t offset; + struct NameValueParserData xml; + char * exif; + int ret = 1; + + img = fopen(path, "r"); + if( !img ) + return(-1); + + fread(&buf, 2, 1, img); + if( (buf[0] != 0xFF) || (buf[1] != 0xD8) ) + { + fclose(img); + return(-1); + } + memset(&buf, 0, sizeof(buf)); + + while( !feof(img) ) + { + while( buf[0] != 0xFF && !feof(img) ) + fread(&buf, 1, 1, img); + + while( buf[0] == 0xFF && !feof(img) ) + fread(&buf, 1, 1, img); + + if( feof(img) ) + break; + + if( buf[0] == 0xE1 ) // APP1 marker + { + offset = 0; + fread(&buf, 2, 1, img); + memcpy(&offset, buf, 2); + offset = SWAP16(offset) - 2; + + if( offset < 30 ) + { + fseek(img, offset, SEEK_CUR); + continue; + } + + data = realloc(data, 30); + fread(data, 29, 1, img); + offset -= 29; + if( strcmp(data, "http://ns.adobe.com/xap/1.0/") != 0 ) + { + fseek(img, offset, SEEK_CUR); + continue; + } + + data = realloc(data, offset+1); + fread(data, offset, 1, img); + + ParseNameValue(data, offset, &xml); + exif = GetValueFromNameValueList(&xml, "DateTimeOriginal"); + if( !exif ) + break; + *date = realloc(*date, strlen(exif)+1); + strcpy(*date, exif); + ClearNameValueList(&xml); + + ret = 0; + break; + } + else + { + offset = 0; + fread(&buf, 2, 1, img); + memcpy(&offset, buf, 2); + offset = SWAP16(offset) - 2; + fseek(img, offset, SEEK_CUR); + } + } + fclose(img); + if( data ) + free(data); + return ret; +} + image * image_new(int32_t width, int32_t height) { diff --git a/image_utils.h b/image_utils.h index c1a4b38..6d712d0 100644 --- a/image_utils.h +++ b/image_utils.h @@ -20,6 +20,9 @@ typedef struct { void image_free(image *pimage); +int +image_get_jpeg_date_xmp(const char * path, char ** date); + int image_get_jpeg_resolution(const char * path, int * width, int * height); diff --git a/metadata.c b/metadata.c index 57ae539..5c48209 100644 --- a/metadata.c +++ b/metadata.c @@ -406,7 +406,6 @@ GetImageMetadata(const char * path, char * name) ExifData *ed; ExifEntry *e = NULL; ExifLoader *l; - ExifTag tag; struct jpeg_decompress_struct cinfo; struct jpeg_error_mgr jerr; FILE *infile; @@ -436,9 +435,8 @@ GetImageMetadata(const char * path, char * name) if( !ed ) goto no_exifdata; - tag = EXIF_TAG_DATE_TIME_ORIGINAL; - e = exif_content_get_entry (ed->ifd[EXIF_IFD_EXIF], tag); - if( e || (e = exif_content_get_entry(ed->ifd[EXIF_IFD_0], EXIF_TAG_DATE_TIME)) ) { + e = exif_content_get_entry (ed->ifd[EXIF_IFD_EXIF], EXIF_TAG_DATE_TIME_ORIGINAL); + if( e || (e = exif_content_get_entry(ed->ifd[EXIF_IFD_EXIF], EXIF_TAG_DATE_TIME_DIGITIZED)) ) { date = strdup(exif_entry_get_value(e, b, sizeof(b))); if( strlen(date) > 10 ) { @@ -451,15 +449,17 @@ GetImageMetadata(const char * path, char * name) date = NULL; } } + else { + /* One last effort to get the date from XMP */ + image_get_jpeg_date_xmp(path, &date); + } //DEBUG DPRINTF(E_DEBUG, L_METADATA, " * date: %s\n", date); - tag = EXIF_TAG_MAKE; - e = exif_content_get_entry (ed->ifd[EXIF_IFD_0], tag); + e = exif_content_get_entry (ed->ifd[EXIF_IFD_0], EXIF_TAG_MAKE); if( e ) { strncpy(make, exif_entry_get_value(e, b, sizeof(b)), sizeof(make)); - tag = EXIF_TAG_MODEL; - e = exif_content_get_entry (ed->ifd[EXIF_IFD_0], tag); + e = exif_content_get_entry (ed->ifd[EXIF_IFD_0], EXIF_TAG_MODEL); if( e ) { strncpy(model, exif_entry_get_value(e, b, sizeof(b)), sizeof(model));