* Fall back to rudimentary XMP parsing when getting image dates from EXIF fails.
This commit is contained in:
parent
c8fe23d838
commit
a26802539f
@ -35,6 +35,7 @@
|
|||||||
#include <jpeglib.h>
|
#include <jpeglib.h>
|
||||||
#include <endian.h>
|
#include <endian.h>
|
||||||
|
|
||||||
|
#include "upnpreplyparse.h"
|
||||||
#include "image_utils.h"
|
#include "image_utils.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
@ -282,6 +283,91 @@ image_get_jpeg_resolution(const char * path, int * width, int * height)
|
|||||||
return ret;
|
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 *
|
||||||
image_new(int32_t width, int32_t height)
|
image_new(int32_t width, int32_t height)
|
||||||
{
|
{
|
||||||
|
@ -20,6 +20,9 @@ typedef struct {
|
|||||||
void
|
void
|
||||||
image_free(image *pimage);
|
image_free(image *pimage);
|
||||||
|
|
||||||
|
int
|
||||||
|
image_get_jpeg_date_xmp(const char * path, char ** date);
|
||||||
|
|
||||||
int
|
int
|
||||||
image_get_jpeg_resolution(const char * path, int * width, int * height);
|
image_get_jpeg_resolution(const char * path, int * width, int * height);
|
||||||
|
|
||||||
|
16
metadata.c
16
metadata.c
@ -406,7 +406,6 @@ GetImageMetadata(const char * path, char * name)
|
|||||||
ExifData *ed;
|
ExifData *ed;
|
||||||
ExifEntry *e = NULL;
|
ExifEntry *e = NULL;
|
||||||
ExifLoader *l;
|
ExifLoader *l;
|
||||||
ExifTag tag;
|
|
||||||
struct jpeg_decompress_struct cinfo;
|
struct jpeg_decompress_struct cinfo;
|
||||||
struct jpeg_error_mgr jerr;
|
struct jpeg_error_mgr jerr;
|
||||||
FILE *infile;
|
FILE *infile;
|
||||||
@ -436,9 +435,8 @@ GetImageMetadata(const char * path, char * name)
|
|||||||
if( !ed )
|
if( !ed )
|
||||||
goto no_exifdata;
|
goto no_exifdata;
|
||||||
|
|
||||||
tag = EXIF_TAG_DATE_TIME_ORIGINAL;
|
e = exif_content_get_entry (ed->ifd[EXIF_IFD_EXIF], 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_EXIF], EXIF_TAG_DATE_TIME_DIGITIZED)) ) {
|
||||||
if( e || (e = exif_content_get_entry(ed->ifd[EXIF_IFD_0], EXIF_TAG_DATE_TIME)) ) {
|
|
||||||
date = strdup(exif_entry_get_value(e, b, sizeof(b)));
|
date = strdup(exif_entry_get_value(e, b, sizeof(b)));
|
||||||
if( strlen(date) > 10 )
|
if( strlen(date) > 10 )
|
||||||
{
|
{
|
||||||
@ -451,15 +449,17 @@ GetImageMetadata(const char * path, char * name)
|
|||||||
date = NULL;
|
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);
|
//DEBUG DPRINTF(E_DEBUG, L_METADATA, " * date: %s\n", date);
|
||||||
|
|
||||||
tag = EXIF_TAG_MAKE;
|
e = exif_content_get_entry (ed->ifd[EXIF_IFD_0], EXIF_TAG_MAKE);
|
||||||
e = exif_content_get_entry (ed->ifd[EXIF_IFD_0], tag);
|
|
||||||
if( e )
|
if( e )
|
||||||
{
|
{
|
||||||
strncpy(make, exif_entry_get_value(e, b, sizeof(b)), sizeof(make));
|
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], EXIF_TAG_MODEL);
|
||||||
e = exif_content_get_entry (ed->ifd[EXIF_IFD_0], tag);
|
|
||||||
if( e )
|
if( e )
|
||||||
{
|
{
|
||||||
strncpy(model, exif_entry_get_value(e, b, sizeof(b)), sizeof(model));
|
strncpy(model, exif_entry_get_value(e, b, sizeof(b)), sizeof(model));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user