mirror of
				https://github.com/flynx/ImageGrid.git
				synced 2025-10-31 03:10:07 +00:00 
			
		
		
		
	reworked metadata caching + updated peer feature (not done yet)...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
		
							parent
							
								
									f9398462c8
								
							
						
					
					
						commit
						49245ba9d1
					
				| @ -57,8 +57,7 @@ var MetadataActions = actions.Actions({ | |||||||
| 			if(this.images && this.images[gid]){ | 			if(this.images && this.images[gid]){ | ||||||
| 				return this.images[gid].metadata || {} | 				return this.images[gid].metadata || {} | ||||||
| 			} | 			} | ||||||
| 			return null | 			return null }], | ||||||
| 		}], |  | ||||||
| 	setMetadata: ['- Image/Set metadata data', | 	setMetadata: ['- Image/Set metadata data', | ||||||
| 		function(image, metadata, merge){ | 		function(image, metadata, merge){ | ||||||
| 			var that = this | 			var that = this | ||||||
| @ -70,12 +69,8 @@ var MetadataActions = actions.Actions({ | |||||||
| 					Object.keys(metadata).forEach(function(k){ | 					Object.keys(metadata).forEach(function(k){ | ||||||
| 						m[k] = metadata[k] | 						m[k] = metadata[k] | ||||||
| 					}) | 					}) | ||||||
| 
 |  | ||||||
| 				} else { | 				} else { | ||||||
| 					this.images[gid].metadata = metadata | 					this.images[gid].metadata = metadata } } }] | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 		}] |  | ||||||
| }) | }) | ||||||
| 
 | 
 | ||||||
| var Metadata =  | var Metadata =  | ||||||
| @ -119,21 +114,19 @@ var MetadataReaderActions = actions.Actions({ | |||||||
| 			var img = this.images && this.images[gid] | 			var img = this.images && this.images[gid] | ||||||
| 
 | 
 | ||||||
| 			if(!image && !img){ | 			if(!image && !img){ | ||||||
| 				return false | 				return false } | ||||||
| 			} |  | ||||||
| 
 | 
 | ||||||
| 			//var full_path = path.normalize(img.base_path +'/'+ img.path)
 | 			//var full_path = path.normalize(img.base_path +'/'+ img.path)
 | ||||||
| 			var full_path = this.getImagePath(gid) | 			var full_path = this.getImagePath(gid) | ||||||
| 
 | 
 | ||||||
| 			return new Promise(function(resolve, reject){ | 			return new Promise(function(resolve, reject){ | ||||||
| 				if(!force && img.metadata){ | 				if(!force  | ||||||
| 					return resolve(img.metadata) | 						&& !(img.metadata || {}).ImageGridPartialMetadata){ | ||||||
| 				} | 					return resolve(img.metadata) } | ||||||
| 
 | 
 | ||||||
| 				fs.readFile(full_path, function(err, file){ | 				fs.readFile(full_path, function(err, file){ | ||||||
| 					if(err){ | 					if(err){ | ||||||
| 						return reject(err) | 						return reject(err) } | ||||||
| 					} |  | ||||||
| 
 | 
 | ||||||
| 					// read stat...
 | 					// read stat...
 | ||||||
| 					if(!that.images[gid].birthtime){ | 					if(!that.images[gid].birthtime){ | ||||||
| @ -173,10 +166,7 @@ var MetadataReaderActions = actions.Actions({ | |||||||
| 							that.markChanged  | 							that.markChanged  | ||||||
| 								&& that.markChanged('images', [gid]) } | 								&& that.markChanged('images', [gid]) } | ||||||
| 
 | 
 | ||||||
| 						resolve(data) }) | 						resolve(data) }) }) }) }], | ||||||
| 				}) |  | ||||||
| 			}) |  | ||||||
| 		}], |  | ||||||
| 
 | 
 | ||||||
| 	// XXX STUB: add support for this to .readMetadata(..)
 | 	// XXX STUB: add support for this to .readMetadata(..)
 | ||||||
| 	readAllMetadata: ['File/Read all metadata', | 	readAllMetadata: ['File/Read all metadata', | ||||||
| @ -202,8 +192,7 @@ var MetadataReaderActions = actions.Actions({ | |||||||
| 					q.enqueue('metadata', read(gid)) | 					q.enqueue('metadata', read(gid)) | ||||||
| 				}) | 				}) | ||||||
| 			 | 			 | ||||||
| 			return q | 			return q }], | ||||||
| 		}], |  | ||||||
| 
 | 
 | ||||||
| 	// XXX take image Metadata and write it to target...
 | 	// XXX take image Metadata and write it to target...
 | ||||||
| 	writeMetadata: ['- Image/Set metadata data', | 	writeMetadata: ['- Image/Set metadata data', | ||||||
| @ -651,9 +640,7 @@ var MetadataUIActions = actions.Actions({ | |||||||
| 						&& (that.config['metadata-graph-config'] = { | 						&& (that.config['metadata-graph-config'] = { | ||||||
| 							graph: this.graph.graph, | 							graph: this.graph.graph, | ||||||
| 							mode: this.graph.mode, | 							mode: this.graph.mode, | ||||||
| 						}) | 						}) }) })], | ||||||
| 				}) |  | ||||||
| 		})], |  | ||||||
| 
 | 
 | ||||||
| 	metadataSection: ['- Image/', | 	metadataSection: ['- Image/', | ||||||
| 		{ sortedActionPriority: 'normal' }, | 		{ sortedActionPriority: 'normal' }, | ||||||
| @ -663,16 +650,18 @@ var MetadataUIActions = actions.Actions({ | |||||||
| 			var field_order = this.config['metadata-field-order'] || [] | 			var field_order = this.config['metadata-field-order'] || [] | ||||||
| 			var x = field_order.length + 1 | 			var x = field_order.length + 1 | ||||||
| 
 | 
 | ||||||
|  | 			// NOTE: this is called on showMetadata.pre in the .handlers 
 | ||||||
|  | 			// 		feature section...
 | ||||||
| 			make.dialog.updateMetadata =  | 			make.dialog.updateMetadata =  | ||||||
| 				function(metadata){ | 				function(metadata){ | ||||||
| 					metadata = metadata || that.getMetadata() | 					metadata = metadata  | ||||||
|  | 						|| that.getMetadata() | ||||||
| 
 | 
 | ||||||
| 					// build new data set and update view...
 | 					// build new data set and update view...
 | ||||||
| 					//this.options.data = _buildInfoList(image, metadata)
 | 					//this.options.data = _buildInfoList(image, metadata)
 | ||||||
| 					this.update() | 					this.update() | ||||||
| 
 | 
 | ||||||
| 					return this | 					return this } | ||||||
| 				} |  | ||||||
| 
 | 
 | ||||||
| 			// build fields...
 | 			// build fields...
 | ||||||
| 			var fields = [] | 			var fields = [] | ||||||
| @ -691,15 +680,12 @@ var MetadataUIActions = actions.Actions({ | |||||||
| 							return | 							return | ||||||
| 
 | 
 | ||||||
| 						} else if(mode == 'disabled') { | 						} else if(mode == 'disabled') { | ||||||
| 							opts.disabled = true | 							opts.disabled = true } } | ||||||
| 						} |  | ||||||
| 					} |  | ||||||
| 
 | 
 | ||||||
| 					fields.push([ | 					fields.push([ | ||||||
| 						[ n + ': ', metadata[k] ],  | 						[ n + ': ', metadata[k] ],  | ||||||
| 						opts, | 						opts, | ||||||
| 					]) | 					]) }) | ||||||
| 				}) |  | ||||||
| 
 | 
 | ||||||
| 			// make fields...
 | 			// make fields...
 | ||||||
| 			fields | 			fields | ||||||
| @ -717,8 +703,7 @@ var MetadataUIActions = actions.Actions({ | |||||||
| 					this.length > 0 | 					this.length > 0 | ||||||
| 						&& make.Separator() }) | 						&& make.Separator() }) | ||||||
| 				.forEach(function(e){ | 				.forEach(function(e){ | ||||||
| 					make(...e) }) | 					make(...e) }) })], | ||||||
| 		})], |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 	// shorthands...
 | 	// shorthands...
 | ||||||
|  | |||||||
| @ -19,114 +19,13 @@ var features = require('lib/features') | |||||||
| var core = require('features/core') | var core = require('features/core') | ||||||
| 
 | 
 | ||||||
| var object = require('lib/object') | var object = require('lib/object') | ||||||
|  | var types = require('lib/types') | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /*********************************************************************/ | /*********************************************************************/ | ||||||
| // helpers...
 | // helpers...
 | ||||||
| 
 | 
 | ||||||
| // Cooperative promise object...
 |  | ||||||
| // 
 |  | ||||||
| // This is like a promise but is not resolved internally, rather this 
 |  | ||||||
| // resolves (is set) via a different promise of value passed to it via 
 |  | ||||||
| // the .set(..) method...
 |  | ||||||
| // 
 |  | ||||||
| // Example:
 |  | ||||||
| // 	// create a promise...
 |  | ||||||
| // 	var p = (new CooperativePromise())
 |  | ||||||
| // 		// bind normally...
 |  | ||||||
| // 		.then(function(){ .. })
 |  | ||||||
| // 		
 |  | ||||||
| // 	// this will resolve p and trigger all the .then(..) callbacks...
 |  | ||||||
| // 	p.set(new Promise(function(resolve, reject){ resolve() }))
 |  | ||||||
| // 	
 |  | ||||||
| // Note that .set(..) can be passed any value, passing a non-promise has
 |  | ||||||
| // the same effect as passing the same value to resolve(..) of a Promise
 |  | ||||||
| // object...
 |  | ||||||
| // 
 |  | ||||||
| // XXX should this be a separate package???
 |  | ||||||
| // XXX can we make this an instance of Promise for passing the
 |  | ||||||
| // 		x instanceof Promise test???
 |  | ||||||
| var CooperativePromisePrototype = { |  | ||||||
| 	__base: null, |  | ||||||
| 	__promise: null, |  | ||||||
| 
 |  | ||||||
| 	// XXX error if already set...
 |  | ||||||
| 	set: function(promise){ |  | ||||||
| 		if(this.__promise == null){ |  | ||||||
| 			// setting a non-promise...
 |  | ||||||
| 			if(promise.catch == null && promise.then == null){ |  | ||||||
| 				Object.defineProperty(this, '__promise', { |  | ||||||
| 					value: false, |  | ||||||
| 					enumerable: false, |  | ||||||
| 				}) |  | ||||||
| 				this.__resolve(promise) |  | ||||||
| 				 |  | ||||||
| 			// setting a promise...
 |  | ||||||
| 			} else { |  | ||||||
| 				Object.defineProperty(this, '__promise', { |  | ||||||
| 					value: promise, |  | ||||||
| 					enumerable: false, |  | ||||||
| 				}) |  | ||||||
| 
 |  | ||||||
| 				// connect the base and the set promises...
 |  | ||||||
| 				promise.catch(this.__reject.bind(this)) |  | ||||||
| 				promise.then(this.__resolve.bind(this)) |  | ||||||
| 
 |  | ||||||
| 				// cleanup...
 |  | ||||||
| 				delete this.__base |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			// cleanup...
 |  | ||||||
| 			delete this.__resolve |  | ||||||
| 			delete this.__reject |  | ||||||
| 
 |  | ||||||
| 		} else { |  | ||||||
| 			// XXX throw err???
 |  | ||||||
| 			console.error('Setting a cooperative promise twice', this) |  | ||||||
| 		} |  | ||||||
| 	}, |  | ||||||
| 
 |  | ||||||
| 	// Promise API...
 |  | ||||||
| 	catch: function(func){ |  | ||||||
| 		return (this.__promise || this.__base).catch(func) }, |  | ||||||
| 	then: function(func){ |  | ||||||
| 		return (this.__promise || this.__base).then(func) }, |  | ||||||
| 
 |  | ||||||
| 	__init__: function(){ |  | ||||||
| 		var that = this |  | ||||||
| 		var base = new Promise(function(resolve, reject){ |  | ||||||
| 			Object.defineProperties(that, { |  | ||||||
| 				__resolve: { |  | ||||||
| 					value: resolve, |  | ||||||
| 					enumerable: false, |  | ||||||
| 					configurable: true, |  | ||||||
| 				}, |  | ||||||
| 				__reject: { |  | ||||||
| 					value: reject, |  | ||||||
| 					enumerable: false, |  | ||||||
| 					configurable: true, |  | ||||||
| 				}, |  | ||||||
| 			}) |  | ||||||
| 		}) |  | ||||||
| 
 |  | ||||||
| 		Object.defineProperty(this, '__base', { |  | ||||||
| 			value: base, |  | ||||||
| 			enumerable: false, |  | ||||||
| 			configurable: true, |  | ||||||
| 		}) |  | ||||||
| 	}, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| var CooperativePromise = |  | ||||||
| module.CooperativePromise = |  | ||||||
| object.Constructor('CooperativePromise',  |  | ||||||
| 	Promise, |  | ||||||
| 	CooperativePromisePrototype) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| //---------------------------------------------------------------------
 |  | ||||||
| 	 |  | ||||||
| // XXX would be nice to list the protocols supported by the action in 
 | // XXX would be nice to list the protocols supported by the action in 
 | ||||||
| // 		an action attr...
 | // 		an action attr...
 | ||||||
| var makeProtocolHandler = | var makeProtocolHandler = | ||||||
| @ -192,8 +91,7 @@ var PeerActions = actions.Actions({ | |||||||
| 					return that.getActionAttr(action, '__peer__') == id } | 					return that.getActionAttr(action, '__peer__') == id } | ||||||
| 				// get all peer actions...
 | 				// get all peer actions...
 | ||||||
| 				: function(action){ | 				: function(action){ | ||||||
| 					return that.getActionAttr(action, '__peer__') }) | 					return that.getActionAttr(action, '__peer__') }) }], | ||||||
| 		}], |  | ||||||
| 	// XXX should this also check props???
 | 	// XXX should this also check props???
 | ||||||
| 	isPeerAction: ['- System/Peer/', | 	isPeerAction: ['- System/Peer/', | ||||||
| 		function(name){ | 		function(name){ | ||||||
| @ -208,9 +106,11 @@ var PeerActions = actions.Actions({ | |||||||
| 	// XXX the events should get called on the peer too -- who is 
 | 	// XXX the events should get called on the peer too -- who is 
 | ||||||
| 	// 		responsible for this???
 | 	// 		responsible for this???
 | ||||||
| 	peerConnect: ['- System/Peer/', | 	peerConnect: ['- System/Peer/', | ||||||
| 		function(id, options){ return new CooperativePromise() }], | 		function(id, options){  | ||||||
|  | 			return new Promise.cooperative() }], | ||||||
| 	peerDisconnect: ['- System/Peer/', | 	peerDisconnect: ['- System/Peer/', | ||||||
| 		function(id){ return new CooperativePromise() }], | 		function(id){  | ||||||
|  | 			return new Promise.cooperative() }], | ||||||
| 
 | 
 | ||||||
| 	// events...
 | 	// events...
 | ||||||
| 	// XXX do proper docs...
 | 	// XXX do proper docs...
 | ||||||
| @ -229,13 +129,14 @@ var PeerActions = actions.Actions({ | |||||||
| 	peerCall: ['- System/Peer/', | 	peerCall: ['- System/Peer/', | ||||||
| 		function(id, action){ | 		function(id, action){ | ||||||
| 			var args = [...arguments].slice(2) | 			var args = [...arguments].slice(2) | ||||||
| 			return this.peerApply(id, action, args) | 			return this.peerApply(id, action, args) }], | ||||||
| 		}], |  | ||||||
| 	peerApply: ['- System/Peer/', | 	peerApply: ['- System/Peer/', | ||||||
| 		function(id, action, args){ return new CooperativePromise() }], | 		function(id, action, args){  | ||||||
|  | 			return new Promise.cooperative() }], | ||||||
| 
 | 
 | ||||||
| 	peerList: ['- System/Peer/', | 	peerList: ['- System/Peer/', | ||||||
| 		function(){ return Object.keys(this.__peers || {}) }], | 		function(){  | ||||||
|  | 			return Object.keys(this.__peers || {}) }], | ||||||
| 
 | 
 | ||||||
| 	// XXX do we need these???
 | 	// XXX do we need these???
 | ||||||
| 	// XXX format spec!!!
 | 	// XXX format spec!!!
 | ||||||
| @ -287,8 +188,7 @@ var ChildProcessPeerActions = actions.Actions({ | |||||||
| 				if(this.__peers  | 				if(this.__peers  | ||||||
| 						&& id in this.__peers  | 						&& id in this.__peers  | ||||||
| 						&& this.__peers[id].peer.connected){ | 						&& this.__peers[id].peer.connected){ | ||||||
| 					return resolve(id)  | 					return resolve(id) } | ||||||
| 				} |  | ||||||
| 
 | 
 | ||||||
| 				this.__peers = this.__peers || {} | 				this.__peers = this.__peers || {} | ||||||
| 
 | 
 | ||||||
| @ -307,13 +207,9 @@ var ChildProcessPeerActions = actions.Actions({ | |||||||
| 
 | 
 | ||||||
| 						callback  | 						callback  | ||||||
| 							&& (delete this.__peer_result_callbacks[msg.id]) | 							&& (delete this.__peer_result_callbacks[msg.id]) | ||||||
| 							&& callback(msg.value, msg.error) | 							&& callback(msg.value, msg.error) } }).bind(this)) | ||||||
| 					} |  | ||||||
| 				}).bind(this)) |  | ||||||
| 
 | 
 | ||||||
| 				resolve(id) | 				resolve(id) }).bind(this)) })], | ||||||
| 			}).bind(this)) |  | ||||||
| 		})], |  | ||||||
| 	// XXX should this call .stop() on the child???
 | 	// XXX should this call .stop() on the child???
 | ||||||
| 	// 		...does the child handle kill gracefully???
 | 	// 		...does the child handle kill gracefully???
 | ||||||
| 	peerDisconnect: ['- System/Peer/', | 	peerDisconnect: ['- System/Peer/', | ||||||
| @ -329,8 +225,7 @@ var ChildProcessPeerActions = actions.Actions({ | |||||||
| 				that.__peers[id].peer.kill() | 				that.__peers[id].peer.kill() | ||||||
| 				delete that.__peers[id] | 				delete that.__peers[id] | ||||||
| 
 | 
 | ||||||
| 			}).bind(this)) | 			}).bind(this)) })], | ||||||
| 		})], |  | ||||||
| 
 | 
 | ||||||
| 	// XXX can we do sync???
 | 	// XXX can we do sync???
 | ||||||
| 	// 		...this would be useful to 100% match the action api and 
 | 	// 		...this would be useful to 100% match the action api and 
 | ||||||
| @ -358,8 +253,7 @@ var ChildProcessPeerActions = actions.Actions({ | |||||||
| 				var handlers = this.__peer_result_callbacks = this.__peer_result_callbacks || {} | 				var handlers = this.__peer_result_callbacks = this.__peer_result_callbacks || {} | ||||||
| 				handlers[call_id] = function(res, err){ err ? reject(err) : resolve(res) } | 				handlers[call_id] = function(res, err){ err ? reject(err) : resolve(res) } | ||||||
| 
 | 
 | ||||||
| 			}).bind(this)) | 			}).bind(this)) })], | ||||||
| 		})], |  | ||||||
| }) | }) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -32,13 +32,19 @@ if(typeof(process) != 'undefined'){ | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /*********************************************************************/ | /*********************************************************************/ | ||||||
|  | // helpers...
 | ||||||
| 
 | 
 | ||||||
| if(typeof(process) != 'undefined'){ | if(typeof(process) != 'undefined'){ | ||||||
| 	var copy = file.denodeify(fse.copy) | 	var copy = file.denodeify(fse.copy) | ||||||
| 	var ensureDir = file.denodeify(fse.ensureDir) | 	var ensureDir = file.denodeify(fse.ensureDir) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function normalizeOrientation(orientation){ | 
 | ||||||
|  | //---------------------------------------------------------------------
 | ||||||
|  | 
 | ||||||
|  | var normalizeOrientation = | ||||||
|  | module.normalizeOrientation = | ||||||
|  | function(orientation){ | ||||||
| 	return { | 	return { | ||||||
| 		orientation: ({ | 		orientation: ({ | ||||||
| 				0: 0, | 				0: 0, | ||||||
| @ -65,9 +71,94 @@ function normalizeOrientation(orientation){ | |||||||
| 	} } | 	} } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| var exifReader2exiftool = { | 
 | ||||||
|  | //---------------------------------------------------------------------
 | ||||||
|  | // Convert image metadata from exif-reader output to format compatible 
 | ||||||
|  | // with exiftool (features/metadata.js)
 | ||||||
|  | 
 | ||||||
|  | // Format:
 | ||||||
|  | // 	{
 | ||||||
|  | // 		// simple key-key pair...
 | ||||||
|  | // 		'path.to.value': 'output-key',
 | ||||||
|  | //
 | ||||||
|  | // 		// key with value handler...
 | ||||||
|  | // 		'path.to.other.value': ['output-key', handler],
 | ||||||
|  | //
 | ||||||
|  | // 		// alias to handler...
 | ||||||
|  | // 		'path.to.yet.another.value': ['output-key', 'path.to.other.value'],
 | ||||||
|  | // 	}
 | ||||||
|  | //
 | ||||||
|  | var EXIF_FORMAT = | ||||||
|  | module.EXIF_FORMAT = { | ||||||
|  | 	// camera / lens...
 | ||||||
|  | 	'image.Make': 'make', | ||||||
|  | 	'image.Model': 'cameraModelName', | ||||||
|  | 	'image.Software': 'software', | ||||||
|  | 	'exif.LensModel': 'lensModel', | ||||||
|  | 
 | ||||||
|  | 	// exposure...
 | ||||||
|  | 	'exif.ISO': 'iso', | ||||||
|  | 	'exif.FNumber': ['fNumber',  | ||||||
|  | 		function(v){ return 'f/'+v }], | ||||||
|  | 	'exif.ExposureTime': ['exposureTime', | ||||||
|  | 		// NOTE: this is a bit of a brute-fore approach but for shutter 
 | ||||||
|  | 		// 		speeds this should not matter...
 | ||||||
|  | 		function(v){ | ||||||
|  | 			if(v > 0.5){ | ||||||
|  | 				return ''+ v } | ||||||
|  | 			for(var d = 1; (v * d) % 1 != 0; d++){} | ||||||
|  | 			return (v * d) +'/'+ d }], | ||||||
|  | 
 | ||||||
|  | 	// dates...
 | ||||||
|  | 	'exif.DateTimeOriginal': ['date/timeOriginal', | ||||||
|  | 		function(v){ | ||||||
|  | 			return v.toShortDate() }], | ||||||
|  | 	'image.ModifyDate': ['modifyDate',  | ||||||
|  | 		'exif.DateTimeOriginal'], | ||||||
|  | 
 | ||||||
|  | 	// IPCT...
 | ||||||
|  | 	'image.Artist': 'artist', | ||||||
|  | 	'image.Copyright': 'copyright', | ||||||
|  | 
 | ||||||
|  | 	// XXX anything else???
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | var exifReader2exiftool =  | ||||||
|  | module.exifReader2exiftool = | ||||||
|  | function(data){ | ||||||
|  | 	return Object.entries(EXIF_FORMAT) | ||||||
|  | 		// handle exif/image/...
 | ||||||
|  | 		.reduce(function(res, [path, to]){ | ||||||
|  | 			var handler | ||||||
|  | 			;[to, handler] = to instanceof Array ? | ||||||
|  | 				to | ||||||
|  | 				: [to] | ||||||
|  | 			// resolve handler reference/alias...
 | ||||||
|  | 			while(typeof(handler) == typeof('str')){ | ||||||
|  | 				handler = EXIF_FORMAT[handler][1] } | ||||||
|  | 			// resolve source path...
 | ||||||
|  | 			var value = path.split(/\./g) | ||||||
|  | 				.reduce(function(res, e){  | ||||||
|  | 					return res && res[e] }, data) | ||||||
|  | 			// set the value...
 | ||||||
|  | 			if(value !== undefined){ | ||||||
|  | 				res[to] = handler ? | ||||||
|  | 					handler(value) | ||||||
|  | 					: value } | ||||||
|  | 			return res }, {}) | ||||||
|  | 		// handle xmp...
 | ||||||
|  | 		.run(function(){ | ||||||
|  | 			var rating = data.xmp  | ||||||
|  | 				// NOTE: we do not need the full XML 
 | ||||||
|  | 				// 		fluff here, just get some values...
 | ||||||
|  | 				&& parseInt( | ||||||
|  | 					(data.xmp.toString() | ||||||
|  | 							.match(/(?<match><(xmp:Rating)[^>]*>(?<value>.*)<\/\2>)/i)  | ||||||
|  | 						|| {groups: {}}) | ||||||
|  | 					.groups.value) | ||||||
|  | 			rating | ||||||
|  | 				&& (this.rating = rating) }) } | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @ -423,9 +514,10 @@ var SharpActions = actions.Actions({ | |||||||
| 				.flat()) }], | 				.flat()) }], | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 	// XXX should this update all images or just the ones that have no metadata???
 | 	// XXX add support for offloading the processing to a thread/worker...
 | ||||||
| 	// XXX would be nice to be able to abort this...
 | 	// XXX would be nice to be able to abort this...
 | ||||||
| 	// 		...and/or have a generic abort protocol triggered when loading...
 | 	// 		...and/or have a generic abort protocol triggered when loading...
 | ||||||
|  | 	// 		...use task queue???
 | ||||||
| 	// XXX make each section optional...
 | 	// XXX make each section optional...
 | ||||||
| 	// XXX revise name...
 | 	// XXX revise name...
 | ||||||
| 	cacheImageMetadata: ['- Sharp|Image/', | 	cacheImageMetadata: ['- Sharp|Image/', | ||||||
| @ -498,6 +590,20 @@ var SharpActions = actions.Actions({ | |||||||
| 							img.orientation = o.orientation || 0 | 							img.orientation = o.orientation || 0 | ||||||
| 							img.flipped = o.flipped | 							img.flipped = o.flipped | ||||||
| 
 | 
 | ||||||
|  | 							// read the metadata...
 | ||||||
|  | 							var exif = metadata.exif  | ||||||
|  | 								&& exifReader(metadata.exif)  | ||||||
|  | 							exif | ||||||
|  | 								&& Object.assign( | ||||||
|  | 									(img.metadata = img.metadata || {}),  | ||||||
|  | 									exifReader2exiftool(exif), | ||||||
|  | 									// mark metadata as partial read...
 | ||||||
|  | 									//
 | ||||||
|  | 									// NOTE: partial metadata will get reread by 
 | ||||||
|  | 									// 		the metadata feature upon request...
 | ||||||
|  | 									// XXX revise name...
 | ||||||
|  | 									{ ImageGridPartialMetadata: true }) | ||||||
|  | 
 | ||||||
| 							// if image too large, generate preview(s)...
 | 							// if image too large, generate preview(s)...
 | ||||||
| 							// XXX EXPERIMENTAL...
 | 							// XXX EXPERIMENTAL...
 | ||||||
| 							var size_threshold = that.config['preview-generate-threshold'] | 							var size_threshold = that.config['preview-generate-threshold'] | ||||||
| @ -513,31 +619,11 @@ var SharpActions = actions.Actions({ | |||||||
| 										base_path, | 										base_path, | ||||||
| 										logger) } | 										logger) } | ||||||
| 
 | 
 | ||||||
| 							// XXX EXIF -- keep compatible with exiftool...
 |  | ||||||
| 							// 		- dates
 |  | ||||||
| 							// 		- camera / lens / ...
 |  | ||||||
| 							var exif = metadata.exif  |  | ||||||
| 								&& exifReader(metadata.exif)  |  | ||||||
| 							// XXX
 |  | ||||||
| 
 |  | ||||||
| 							// xmp:Rating...
 |  | ||||||
| 							var rating = metadata.xmp  |  | ||||||
| 								// NOTE: we do not need the full XML 
 |  | ||||||
| 								// 		fluff here, just get some values...
 |  | ||||||
| 								&& parseInt( |  | ||||||
| 									(metadata.xmp.toString() |  | ||||||
| 											.match(/(?<match><(xmp:Rating)[^>]*>(?<value>.*)<\/\2>)/i)  |  | ||||||
| 										|| {groups: {}}) |  | ||||||
| 									.groups.value) |  | ||||||
| 							rating |  | ||||||
| 								&& (img.metadata = img.metadata || {}) |  | ||||||
| 								&& (img.metadata.rating = rating || 0) |  | ||||||
| 
 |  | ||||||
| 							that.markChanged('images', [gid]) | 							that.markChanged('images', [gid]) | ||||||
| 
 | 
 | ||||||
| 							logger && logger.emit('done', gid) | 							logger && logger.emit('done', gid) | ||||||
| 
 | 
 | ||||||
| 							// update image to use the orientation...
 | 							// update loaded image to use the orientation...
 | ||||||
| 							loaded | 							loaded | ||||||
| 								&& loaded.has(gid) | 								&& loaded.has(gid) | ||||||
| 								&& that.ribbons.updateImage(gid)  | 								&& that.ribbons.updateImage(gid)  | ||||||
| @ -564,9 +650,11 @@ module.Sharp = core.ImageGridFeatures.Feature({ | |||||||
| 
 | 
 | ||||||
| 	handlers: [ | 	handlers: [ | ||||||
| 		/* XXX not sure if we need this... | 		/* XXX not sure if we need this... | ||||||
|  | 		// XXX this is best done in a thread + needs to be abortable...
 | ||||||
| 		['loadImages', | 		['loadImages', | ||||||
| 			function(){ | 			function(){ | ||||||
| 				this.cacheImageMetadata('all', false) }], | 				//this.cacheImageMetadata('all', false) }],
 | ||||||
|  | 				this.cacheImageMetadata('all') }], | ||||||
| 		//*/
 | 		//*/
 | ||||||
| 
 | 
 | ||||||
| 		// set orientation if not defined...
 | 		// set orientation if not defined...
 | ||||||
|  | |||||||
							
								
								
									
										6
									
								
								Viewer/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										6
									
								
								Viewer/package-lock.json
									
									
									
										generated
									
									
									
								
							| @ -1117,9 +1117,9 @@ | |||||||
|       "integrity": "sha512-EzT4CP6d6lI8bnknNgT3W8mUQhSVXflO0yPbKD4dKsFcINiC6npjoEBz+8m3VQmWJhc+36pXD4JLwNxUEgzi+Q==" |       "integrity": "sha512-EzT4CP6d6lI8bnknNgT3W8mUQhSVXflO0yPbKD4dKsFcINiC6npjoEBz+8m3VQmWJhc+36pXD4JLwNxUEgzi+Q==" | ||||||
|     }, |     }, | ||||||
|     "ig-types": { |     "ig-types": { | ||||||
|       "version": "2.0.21", |       "version": "3.0.1", | ||||||
|       "resolved": "https://registry.npmjs.org/ig-types/-/ig-types-2.0.21.tgz", |       "resolved": "https://registry.npmjs.org/ig-types/-/ig-types-3.0.1.tgz", | ||||||
|       "integrity": "sha512-s+Hu9MU50iohoS/5SUwuoS+P2EHk7Z2zKx9wX3syiBsaL9HYq8g/0Yp/4yz9JkME1zpbS8r9aviR0O2rjBXwHQ==", |       "integrity": "sha512-oa0Tq+LFyy/2SoQHfhRoa39AtttslJFm95FaF7wH5FNcjxRn3dJ/C/4LscXIoeGaDcXe2DyneVIPNnvg8IOsNw==", | ||||||
|       "requires": { |       "requires": { | ||||||
|         "ig-object": "^5.2.8", |         "ig-object": "^5.2.8", | ||||||
|         "object-run": "^1.0.1" |         "object-run": "^1.0.1" | ||||||
|  | |||||||
| @ -32,7 +32,7 @@ | |||||||
|     "ig-argv": "^2.15.0", |     "ig-argv": "^2.15.0", | ||||||
|     "ig-features": "^3.4.2", |     "ig-features": "^3.4.2", | ||||||
|     "ig-object": "^5.2.8", |     "ig-object": "^5.2.8", | ||||||
|     "ig-types": "^2.0.21", |     "ig-types": "^3.0.1", | ||||||
|     "moment": "^2.29.1", |     "moment": "^2.29.1", | ||||||
|     "object-run": "^1.0.1", |     "object-run": "^1.0.1", | ||||||
|     "requirejs": "^2.3.6", |     "requirejs": "^2.3.6", | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user