* Fall back to rudimentary XMP parsing when getting image dates from EXIF fails.
This commit is contained in:
		@@ -35,6 +35,7 @@
 | 
			
		||||
#include <jpeglib.h>
 | 
			
		||||
#include <endian.h>
 | 
			
		||||
 | 
			
		||||
#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)
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										16
									
								
								metadata.c
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								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));
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user