* 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 <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));
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user