| 
									
										
										
										
											2016-05-22 21:10:37 +03:00
										 |  |  | /********************************************************************** | 
					
						
							|  |  |  | *  | 
					
						
							|  |  |  | * | 
					
						
							|  |  |  | * | 
					
						
							|  |  |  | **********************************************************************/ | 
					
						
							| 
									
										
										
										
											2016-08-21 02:19:24 +03:00
										 |  |  | ((typeof define)[0]=='u'?function(f){module.exports=f(require)}:define) | 
					
						
							|  |  |  | (function(require){ var module={} // make module AMD/node compatible...
 | 
					
						
							| 
									
										
										
										
											2016-08-20 22:49:36 +03:00
										 |  |  | /*********************************************************************/ | 
					
						
							| 
									
										
										
										
											2016-05-22 21:10:37 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | var actions = require('lib/actions') | 
					
						
							|  |  |  | var features = require('lib/features') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var core = require('features/core') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | try{ | 
					
						
							|  |  |  | 	var sharp = requirejs('sharp') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } catch(err){ | 
					
						
							| 
									
										
										
										
											2016-05-25 22:09:03 +03:00
										 |  |  | 	var sharp = null | 
					
						
							| 
									
										
										
										
											2016-05-22 21:10:37 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | if(typeof(process) != 'undefined'){ | 
					
						
							| 
									
										
										
										
											2016-05-22 23:11:12 +03:00
										 |  |  | 	var cp = requirejs('child_process') | 
					
						
							| 
									
										
										
										
											2016-05-22 21:10:37 +03:00
										 |  |  | 	var fse = requirejs('fs-extra') | 
					
						
							|  |  |  | 	var pathlib = requirejs('path') | 
					
						
							|  |  |  | 	var glob = requirejs('glob') | 
					
						
							| 
									
										
										
										
											2020-11-02 03:16:01 +03:00
										 |  |  | 	var exifReader = requirejs('exif-reader') | 
					
						
							| 
									
										
										
										
											2016-05-28 16:29:57 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-01 16:12:10 +03:00
										 |  |  | 	var file = require('imagegrid/file') | 
					
						
							| 
									
										
										
										
											2016-05-22 21:10:37 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*********************************************************************/ | 
					
						
							| 
									
										
										
										
											2020-11-03 04:49:56 +03:00
										 |  |  | // helpers...
 | 
					
						
							| 
									
										
										
										
											2016-05-22 21:10:37 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | if(typeof(process) != 'undefined'){ | 
					
						
							| 
									
										
										
										
											2020-10-30 18:13:53 +03:00
										 |  |  | 	var copy = file.denodeify(fse.copy) | 
					
						
							| 
									
										
										
										
											2016-05-22 21:10:37 +03:00
										 |  |  | 	var ensureDir = file.denodeify(fse.ensureDir) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-03 04:49:56 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | //---------------------------------------------------------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var normalizeOrientation = | 
					
						
							|  |  |  | module.normalizeOrientation = | 
					
						
							|  |  |  | function(orientation){ | 
					
						
							| 
									
										
										
										
											2016-06-03 04:46:51 +03:00
										 |  |  | 	return { | 
					
						
							|  |  |  | 		orientation: ({ | 
					
						
							|  |  |  | 				0: 0, | 
					
						
							|  |  |  | 				1: 0, | 
					
						
							|  |  |  | 				2: 0, | 
					
						
							|  |  |  | 				3: 180, | 
					
						
							|  |  |  | 				4: 0, | 
					
						
							|  |  |  | 				5: 90, | 
					
						
							|  |  |  | 				6: 90, | 
					
						
							|  |  |  | 				7: 90,  | 
					
						
							|  |  |  | 				8: 270, | 
					
						
							|  |  |  | 			})[orientation], | 
					
						
							|  |  |  | 		flipped: ({ | 
					
						
							|  |  |  | 				0: null, | 
					
						
							|  |  |  | 				1: null, | 
					
						
							|  |  |  | 				2: ['horizontal'], | 
					
						
							|  |  |  | 				3: null, | 
					
						
							|  |  |  | 				4: ['vertical'], | 
					
						
							|  |  |  | 				5: ['vertical'], | 
					
						
							|  |  |  | 				6: null, | 
					
						
							|  |  |  | 				7: ['horizontal'], | 
					
						
							|  |  |  | 				8: null, | 
					
						
							|  |  |  | 			})[orientation], | 
					
						
							| 
									
										
										
										
											2020-10-31 05:10:51 +03:00
										 |  |  | 	} } | 
					
						
							| 
									
										
										
										
											2016-06-03 04:46:51 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-22 21:10:37 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-03 04:49:56 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | //---------------------------------------------------------------------
 | 
					
						
							|  |  |  | // 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???
 | 
					
						
							| 
									
										
										
										
											2020-11-02 03:16:01 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-03 04:49:56 +03:00
										 |  |  | 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) }) } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-02 03:16:01 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-28 16:29:57 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-22 21:10:37 +03:00
										 |  |  | /*********************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var SharpActions = actions.Actions({ | 
					
						
							|  |  |  | 	config: { | 
					
						
							|  |  |  | 		'preview-normalized': true, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-07 18:13:52 +03:00
										 |  |  | 		// can be:
 | 
					
						
							|  |  |  | 		// 	'gids'
 | 
					
						
							|  |  |  | 		// 	'files'
 | 
					
						
							|  |  |  | 		'preview-progress-mode': 'gids', | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-02 05:33:29 +03:00
										 |  |  | 		'preview-generate-threshold': 2000, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-26 05:36:28 +03:00
										 |  |  | 		// NOTE: this uses 'preview-sizes' and 'preview-path-template' 
 | 
					
						
							|  |  |  | 		// 		from filesystem.IndexFormat...
 | 
					
						
							| 
									
										
										
										
											2016-05-22 21:10:37 +03:00
										 |  |  | 	}, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-01 15:25:50 +03:00
										 |  |  | 	// XXX need to distinguish if something was written in the promise chain...
 | 
					
						
							| 
									
										
										
										
											2020-10-31 05:10:51 +03:00
										 |  |  | 	// 		...return false???
 | 
					
						
							|  |  |  | 	// 		......should the return value be a bit more informative???
 | 
					
						
							|  |  |  | 	// 		something like:
 | 
					
						
							|  |  |  | 	// 			{
 | 
					
						
							|  |  |  | 	// 				gid: ..
 | 
					
						
							|  |  |  | 	// 				path: ..
 | 
					
						
							|  |  |  | 	// 				status: ..
 | 
					
						
							|  |  |  | 	// 				...
 | 
					
						
							|  |  |  | 	// 			}
 | 
					
						
							| 
									
										
										
										
											2020-10-30 19:16:42 +03:00
										 |  |  | 	// XXX make backup name pattern configurable...
 | 
					
						
							| 
									
										
										
										
											2020-10-31 02:44:11 +03:00
										 |  |  | 	// XXX add crop support...
 | 
					
						
							| 
									
										
										
										
											2020-10-30 18:13:53 +03:00
										 |  |  | 	makeResizedImage: ['- Image/', | 
					
						
							|  |  |  | 		core.doc`Make resized image(s)...
 | 
					
						
							| 
									
										
										
										
											2016-05-23 17:54:11 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-30 18:13:53 +03:00
										 |  |  | 			.makeResizedImage(gid, size, path[, options]) | 
					
						
							|  |  |  | 			.makeResizedImage(gids, size, path[, options]) | 
					
						
							|  |  |  | 				-> promise | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		Image size formats: | 
					
						
							|  |  |  | 			500px		- resize to make image's *largest* dimension 500 pixels (default). | 
					
						
							|  |  |  | 			500p		- resize to make image's *smallest* dimension 500 pixels. | 
					
						
							|  |  |  | 			500			- same as 500px | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		options format: | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				// output image name...
 | 
					
						
							|  |  |  | 				//
 | 
					
						
							|  |  |  | 				// Used if processing a single image, ignored otherwise.
 | 
					
						
							| 
									
										
										
										
											2020-10-30 19:16:42 +03:00
										 |  |  | 				name: null | <str>, | 
					
						
							| 
									
										
										
										
											2020-10-30 18:13:53 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				// image name pattern and data...
 | 
					
						
							|  |  |  | 				//
 | 
					
						
							|  |  |  | 				// NOTE: for more info on pattern see: .formatImageName(..)
 | 
					
						
							| 
									
										
										
										
											2020-10-30 19:16:42 +03:00
										 |  |  | 				pattern: null | <str>, | 
					
						
							|  |  |  | 				data: null | { .. }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// if true and image is smaller than size enlarge it...
 | 
					
						
							|  |  |  | 				// 
 | 
					
						
							|  |  |  | 				// default: null / false
 | 
					
						
							|  |  |  | 				enlarge: null | true, | 
					
						
							| 
									
										
										
										
											2020-10-30 18:13:53 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				// overwrite, backup or skip (default) existing images...
 | 
					
						
							|  |  |  | 				//
 | 
					
						
							|  |  |  | 				// default: null / false
 | 
					
						
							| 
									
										
										
										
											2020-10-30 19:16:42 +03:00
										 |  |  | 				overwrite: null | true | 'backup', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// if true do not write an image if it's smaller than size...
 | 
					
						
							|  |  |  | 				// 
 | 
					
						
							|  |  |  | 				// default: null / false
 | 
					
						
							|  |  |  | 				skipSmaller: null | true, | 
					
						
							| 
									
										
										
										
											2020-10-30 18:13:53 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				// XXX not implemented...
 | 
					
						
							|  |  |  | 				transform: ..., | 
					
						
							|  |  |  | 				crop: ..., | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-31 02:10:27 +03:00
										 |  |  | 				timestamp: ..., | 
					
						
							|  |  |  | 				logger: ..., | 
					
						
							| 
									
										
										
										
											2020-10-30 18:13:53 +03:00
										 |  |  | ,			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-30 19:16:42 +03:00
										 |  |  | 		NOTE: all options are optional. | 
					
						
							| 
									
										
										
										
											2020-10-30 18:13:53 +03:00
										 |  |  | 		NOTE: this will not overwrite existing images. | 
					
						
							|  |  |  | 		`,
 | 
					
						
							|  |  |  | 		function(images, size, path, options={}){ | 
					
						
							|  |  |  | 			var that = this | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// sanity check...
 | 
					
						
							|  |  |  | 			if(arguments.length < 3){ | 
					
						
							|  |  |  | 				throw new Error('.makeResizedImage(..): ' | 
					
						
							|  |  |  | 					+'need at least images, size and path.') } | 
					
						
							|  |  |  | 			// get/normalize images...
 | 
					
						
							|  |  |  | 			//images = images || this.current
 | 
					
						
							|  |  |  | 			images = images  | 
					
						
							|  |  |  | 				|| 'all' | 
					
						
							|  |  |  | 			// keywords...
 | 
					
						
							|  |  |  | 			images = images == 'all' ?  | 
					
						
							|  |  |  | 					this.data.getImages('all') | 
					
						
							|  |  |  | 				: images == 'current' ?  | 
					
						
							|  |  |  | 					this.current | 
					
						
							|  |  |  | 				: images | 
					
						
							|  |  |  | 			images = images instanceof Array ?  | 
					
						
							|  |  |  | 				images  | 
					
						
							|  |  |  | 				: [images] | 
					
						
							|  |  |  | 			// sizing...
 | 
					
						
							|  |  |  | 			var fit =  | 
					
						
							|  |  |  | 				typeof(size) == typeof('str') ? | 
					
						
							|  |  |  | 					(size.endsWith('px') ? | 
					
						
							|  |  |  | 						'inside' | 
					
						
							|  |  |  | 					: size.endsWith('p') ? | 
					
						
							|  |  |  | 						'outside' | 
					
						
							|  |  |  | 					: 'inside') | 
					
						
							|  |  |  | 				: 'inside' | 
					
						
							|  |  |  | 			size = parseInt(size) | 
					
						
							|  |  |  | 			// options...
 | 
					
						
							|  |  |  | 			var { | 
					
						
							|  |  |  | 				// naming...
 | 
					
						
							|  |  |  | 				name,  | 
					
						
							|  |  |  | 				pattern,  | 
					
						
							|  |  |  | 				data,  | 
					
						
							| 
									
										
										
										
											2020-10-30 19:16:42 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-30 18:13:53 +03:00
										 |  |  | 				// file handling...
 | 
					
						
							| 
									
										
										
										
											2020-10-30 19:16:42 +03:00
										 |  |  | 				enlarge, | 
					
						
							|  |  |  | 				skipSmaller, | 
					
						
							| 
									
										
										
										
											2020-10-30 18:13:53 +03:00
										 |  |  | 				overwrite, | 
					
						
							| 
									
										
										
										
											2020-10-30 19:16:42 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-30 18:13:53 +03:00
										 |  |  | 				// transformations...
 | 
					
						
							|  |  |  | 				transform,  | 
					
						
							|  |  |  | 				// XXX not implemented...
 | 
					
						
							|  |  |  | 				crop,  | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-31 02:10:27 +03:00
										 |  |  | 				timestamp, | 
					
						
							| 
									
										
										
										
											2020-10-30 18:13:53 +03:00
										 |  |  | 				logger,  | 
					
						
							|  |  |  | 			} = options | 
					
						
							|  |  |  | 			// defaults...
 | 
					
						
							|  |  |  | 			pattern = pattern || '%n' | 
					
						
							|  |  |  | 			transform = transform === undefined ?  | 
					
						
							|  |  |  | 				true  | 
					
						
							|  |  |  | 				: transform | 
					
						
							| 
									
										
										
										
											2020-10-31 02:10:27 +03:00
										 |  |  | 			timestamp = timestamp || Date.timeStamp() | 
					
						
							| 
									
										
										
										
											2020-11-01 15:24:22 +03:00
										 |  |  | 			logger = logger !== false ? | 
					
						
							|  |  |  | 				(logger || this.logger) | 
					
						
							|  |  |  | 				: false | 
					
						
							| 
									
										
										
										
											2020-10-30 18:13:53 +03:00
										 |  |  | 			logger = logger && logger.push('Resize') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-30 19:24:38 +03:00
										 |  |  | 			// backup...
 | 
					
						
							|  |  |  | 			// XXX make backup name pattern configurable...
 | 
					
						
							|  |  |  | 			var backupName = function(to){ | 
					
						
							|  |  |  | 				var i = 0 | 
					
						
							|  |  |  | 				while(fse.existsSync(`${to}.${timestamp}.bak`+ (i || ''))){ | 
					
						
							|  |  |  | 					i++ } | 
					
						
							|  |  |  | 				return `${to}.${timestamp}.bak`+ (i || '') } | 
					
						
							| 
									
										
										
										
											2020-10-30 18:13:53 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			return Promise.all(images | 
					
						
							|  |  |  | 				.map(function(gid){ | 
					
						
							|  |  |  | 					// skip non-images...
 | 
					
						
							| 
									
										
										
										
											2020-11-01 15:24:22 +03:00
										 |  |  | 					if(!['image', null, undefined] | 
					
						
							|  |  |  | 							.includes(that.images[gid].type)){ | 
					
						
							| 
									
										
										
										
											2020-10-31 05:10:51 +03:00
										 |  |  | 						return false } | 
					
						
							| 
									
										
										
										
											2020-10-30 18:13:53 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 					// paths...
 | 
					
						
							|  |  |  | 					var source = that.getImagePath(gid) | 
					
						
							|  |  |  | 					var to = pathlib.join( | 
					
						
							|  |  |  | 						path,  | 
					
						
							|  |  |  | 						(images.length == 1 && name) ? | 
					
						
							|  |  |  | 							name | 
					
						
							|  |  |  | 							: that.formatImageName(pattern, gid, data || {})) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					logger && logger.emit('queued', to) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-30 19:16:42 +03:00
										 |  |  | 					var img = sharp(source) | 
					
						
							|  |  |  | 					return (skipSmaller ? | 
					
						
							| 
									
										
										
										
											2020-10-30 19:24:38 +03:00
										 |  |  | 							// skip if smaller than size...
 | 
					
						
							| 
									
										
										
										
											2020-10-30 19:16:42 +03:00
										 |  |  | 							img | 
					
						
							|  |  |  | 								.metadata() | 
					
						
							|  |  |  | 								.then(function(m){ | 
					
						
							|  |  |  | 									// skip...
 | 
					
						
							|  |  |  | 									if((fit == 'inside' | 
					
						
							|  |  |  | 												&& Math.max(m.width, m.height) < size) | 
					
						
							|  |  |  | 											|| (fit == 'outside' | 
					
						
							|  |  |  | 												&& Math.min(m.width, m.height) < size)){ | 
					
						
							| 
									
										
										
										
											2020-11-05 06:31:13 +03:00
										 |  |  | 										skipping(gid) | 
					
						
							|  |  |  | 										return } | 
					
						
							| 
									
										
										
										
											2020-10-30 19:24:38 +03:00
										 |  |  | 									// continue...
 | 
					
						
							| 
									
										
										
										
											2020-10-30 19:16:42 +03:00
										 |  |  | 									return img }) | 
					
						
							|  |  |  | 							: Promise.resolve(img)) | 
					
						
							| 
									
										
										
										
											2020-10-30 19:24:38 +03:00
										 |  |  | 						// prepare to write...
 | 
					
						
							| 
									
										
										
										
											2020-10-30 19:16:42 +03:00
										 |  |  | 						.then(function(img){ | 
					
						
							|  |  |  | 							return img  | 
					
						
							|  |  |  | 								&& ensureDir(pathlib.dirname(to)) | 
					
						
							|  |  |  | 									.then(function(){ | 
					
						
							|  |  |  | 										// handle existing image...
 | 
					
						
							|  |  |  | 										if(fse.existsSync(to)){ | 
					
						
							|  |  |  | 											// rename...
 | 
					
						
							|  |  |  | 											if(overwrite == 'backup'){ | 
					
						
							| 
									
										
										
										
											2020-10-30 19:24:38 +03:00
										 |  |  | 												fse.renameSync(to, backupName(to)) | 
					
						
							| 
									
										
										
										
											2020-10-30 19:16:42 +03:00
										 |  |  | 											// remove...
 | 
					
						
							|  |  |  | 											} else if(overwrite){ | 
					
						
							|  |  |  | 												fse.removeSync(to) | 
					
						
							|  |  |  | 											// skip...
 | 
					
						
							|  |  |  | 											} else { | 
					
						
							| 
									
										
										
										
											2020-11-05 06:31:13 +03:00
										 |  |  | 												skipping(gid) | 
					
						
							|  |  |  | 												return } } | 
					
						
							| 
									
										
										
										
											2020-10-30 19:16:42 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 										// write...
 | 
					
						
							|  |  |  | 										return img | 
					
						
							|  |  |  | 											.clone() | 
					
						
							|  |  |  | 											// handle transform (.orientation / .flip) and .crop...
 | 
					
						
							|  |  |  | 											.run(function(){ | 
					
						
							| 
									
										
										
										
											2020-10-31 02:10:27 +03:00
										 |  |  | 												var img_data = that.images[gid] | 
					
						
							|  |  |  | 												if(transform && (img_data.orientation || img_data.flipped)){ | 
					
						
							|  |  |  | 													img_data.orientation | 
					
						
							|  |  |  | 														&& this.rotate(img_data.orientation) | 
					
						
							|  |  |  | 													img_data.flipped | 
					
						
							|  |  |  | 														&& img_data.flipped.includes('horizontal') | 
					
						
							|  |  |  | 														&& this.flip() } | 
					
						
							|  |  |  | 													img_data.flipped | 
					
						
							|  |  |  | 														&& img_data.flipped.includes('vertical') | 
					
						
							|  |  |  | 														&& this.flop()  | 
					
						
							| 
									
										
										
										
											2020-10-30 19:16:42 +03:00
										 |  |  | 												// XXX
 | 
					
						
							|  |  |  | 												if(crop){ | 
					
						
							|  |  |  | 													// XXX
 | 
					
						
							|  |  |  | 												} | 
					
						
							|  |  |  | 											}) | 
					
						
							|  |  |  | 											.resize({ | 
					
						
							|  |  |  | 												width: size, | 
					
						
							|  |  |  | 												height: size, | 
					
						
							|  |  |  | 												fit: fit, | 
					
						
							|  |  |  | 												withoutEnlargement: !enlarge, | 
					
						
							|  |  |  | 											}) | 
					
						
							|  |  |  | 											.withMetadata() | 
					
						
							|  |  |  | 											.toFile(to)  | 
					
						
							|  |  |  | 											.then(function(){ | 
					
						
							|  |  |  | 												logger  | 
					
						
							| 
									
										
										
										
											2020-10-31 05:10:51 +03:00
										 |  |  | 													&& logger.emit('done', to)  | 
					
						
							|  |  |  | 												return img }) }) }) })) }], | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// XXX test against .makePreviews(..) for speed...
 | 
					
						
							| 
									
										
										
										
											2020-11-01 15:24:22 +03:00
										 |  |  | 	// XXX this does not update image.base_path -- is this correct???
 | 
					
						
							|  |  |  | 	// XXX do we need to be able to run this in a worker???
 | 
					
						
							|  |  |  | 	makePreviews: ['Sharp|File/Make image $previews', | 
					
						
							|  |  |  | 		core.doc`Make image previews
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			Make previews for all images... | 
					
						
							|  |  |  | 			.makePreviews() | 
					
						
							|  |  |  | 			.makePreviews('all') | 
					
						
							| 
									
										
										
										
											2020-11-02 03:16:01 +03:00
										 |  |  | 				-> promise | 
					
						
							| 
									
										
										
										
											2020-11-01 15:24:22 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			Make previews for current image... | 
					
						
							|  |  |  | 			.makePreviews('current') | 
					
						
							| 
									
										
										
										
											2020-11-02 03:16:01 +03:00
										 |  |  | 				-> promise | 
					
						
							| 
									
										
										
										
											2020-11-01 15:24:22 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			Make previews for specific image(s)... | 
					
						
							|  |  |  | 			.makePreviews(gid) | 
					
						
							|  |  |  | 			.makePreviews([gid, gid, ..]) | 
					
						
							| 
									
										
										
										
											2020-11-02 03:16:01 +03:00
										 |  |  | 				-> promise | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			Make previews of images, size and at base_path... | 
					
						
							|  |  |  | 			.makePreviews(images, sizes) | 
					
						
							|  |  |  | 			.makePreviews(images, sizes, base_path) | 
					
						
							|  |  |  | 				-> promise | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-01 15:24:22 +03:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2020-11-02 03:16:01 +03:00
										 |  |  | 		NOTE: if base_path is given .images will not be updated with new  | 
					
						
							|  |  |  | 			preview paths... | 
					
						
							| 
									
										
										
										
											2020-11-01 15:24:22 +03:00
										 |  |  | 		`,
 | 
					
						
							| 
									
										
										
										
											2020-10-31 05:10:51 +03:00
										 |  |  | 		function(images, sizes, base_path, logger){ | 
					
						
							|  |  |  | 			var that = this | 
					
						
							| 
									
										
										
										
											2020-11-01 15:24:22 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			var logger_mode = this.config['preview-progress-mode'] || 'gids' | 
					
						
							|  |  |  | 			logger = logger !== false ? | 
					
						
							|  |  |  | 				(logger || this.logger) | 
					
						
							|  |  |  | 				: false | 
					
						
							|  |  |  | 			var gid_logger = logger && logger.push('Images') | 
					
						
							| 
									
										
										
										
											2020-10-31 05:10:51 +03:00
										 |  |  | 			logger = logger && logger.push('Previews') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-01 15:24:22 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-31 05:10:51 +03:00
										 |  |  | 			// get/normalize images...
 | 
					
						
							|  |  |  | 			//images = images || this.current
 | 
					
						
							|  |  |  | 			images = images  | 
					
						
							|  |  |  | 				|| 'all' | 
					
						
							|  |  |  | 			// keywords...
 | 
					
						
							|  |  |  | 			images = images == 'all' ?  | 
					
						
							|  |  |  | 					this.data.getImages('all') | 
					
						
							|  |  |  | 				: images == 'current' ?  | 
					
						
							|  |  |  | 					this.current | 
					
						
							|  |  |  | 				: images | 
					
						
							|  |  |  | 			images = images instanceof Array ?  | 
					
						
							|  |  |  | 				images  | 
					
						
							|  |  |  | 				: [images] | 
					
						
							|  |  |  | 			// get/normalize sizes....
 | 
					
						
							|  |  |  | 			var cfg_sizes = this.config['preview-sizes'].slice() || [] | 
					
						
							|  |  |  | 			cfg_sizes | 
					
						
							|  |  |  | 				.sort() | 
					
						
							|  |  |  | 				.reverse() | 
					
						
							|  |  |  | 			// XXX revise...
 | 
					
						
							|  |  |  | 			if(sizes){ | 
					
						
							|  |  |  | 				sizes = sizes instanceof Array ? sizes : [sizes] | 
					
						
							|  |  |  | 				// normalize to preview size...
 | 
					
						
							|  |  |  | 				sizes = (this.config['preview-normalized'] ?  | 
					
						
							|  |  |  | 					sizes | 
					
						
							|  |  |  | 						.map(function(s){  | 
					
						
							|  |  |  | 							return cfg_sizes.filter(function(c){ return c >= s }).pop() || s }) | 
					
						
							|  |  |  | 					: sizes) | 
					
						
							|  |  |  | 						.unique() | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				sizes = cfg_sizes } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			var path_tpl = that.config['preview-path-template'] | 
					
						
							|  |  |  | 				.replace(/\$INDEX|\$\{INDEX\}/g, that.config['index-dir'] || '.ImageGrid') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			return Promise.all(images | 
					
						
							|  |  |  | 				.map(function(gid){ | 
					
						
							|  |  |  | 					var img = that.images[gid] | 
					
						
							|  |  |  | 					var base = base_path  | 
					
						
							|  |  |  | 						|| img.base_path  | 
					
						
							|  |  |  | 						|| that.location.path | 
					
						
							| 
									
										
										
										
											2020-11-01 15:24:22 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 					gid_logger && gid_logger.emit('queued', gid) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-31 05:10:51 +03:00
										 |  |  | 					return sizes | 
					
						
							| 
									
										
										
										
											2020-11-01 15:24:22 +03:00
										 |  |  | 						.map(function(size, i){ | 
					
						
							| 
									
										
										
										
											2020-10-31 05:10:51 +03:00
										 |  |  | 							var name = path = path_tpl | 
					
						
							|  |  |  | 								.replace(/\$RESOLUTION|\$\{RESOLUTION\}/g, parseInt(size)) | 
					
						
							|  |  |  | 								.replace(/\$GID|\$\{GID\}/g, gid)  | 
					
						
							|  |  |  | 								.replace(/\$NAME|\$\{NAME\}/g, img.name) | 
					
						
							|  |  |  | 							return that.makeResizedImage(gid, size, base, {  | 
					
						
							|  |  |  | 									name,  | 
					
						
							|  |  |  | 									skipSmaller: true, | 
					
						
							|  |  |  | 									transform: false, | 
					
						
							| 
									
										
										
										
											2020-11-01 15:24:22 +03:00
										 |  |  | 									logger: logger_mode == 'gids' ?  | 
					
						
							|  |  |  | 										false  | 
					
						
							|  |  |  | 										: logger, | 
					
						
							| 
									
										
										
										
											2020-10-31 05:10:51 +03:00
										 |  |  | 								}) | 
					
						
							|  |  |  | 								.then(function([res]){ | 
					
						
							| 
									
										
										
										
											2020-11-01 15:24:22 +03:00
										 |  |  | 									i == sizes.length-1 | 
					
						
							|  |  |  | 										&& gid_logger && gid_logger.emit('done', gid) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 									// did not create a preview...
 | 
					
						
							| 
									
										
										
										
											2020-10-31 05:10:51 +03:00
										 |  |  | 									if(!res){ | 
					
						
							|  |  |  | 										return false } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 									// update metadata...
 | 
					
						
							| 
									
										
										
										
											2020-11-02 03:16:01 +03:00
										 |  |  | 									if(!base_path){ | 
					
						
							|  |  |  | 										var preview = img.preview = img.preview || {}  | 
					
						
							|  |  |  | 										preview[parseInt(size) + 'px'] = name | 
					
						
							| 
									
										
										
										
											2020-11-05 06:31:13 +03:00
										 |  |  | 										that.markChanged | 
					
						
							|  |  |  | 											&& that.markChanged('images', [gid]) } | 
					
						
							| 
									
										
										
										
											2020-10-31 05:10:51 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 									return [gid, size, name] }) }) }) | 
					
						
							|  |  |  | 				.flat()) }], | 
					
						
							| 
									
										
										
										
											2020-11-02 03:16:01 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-03 04:49:56 +03:00
										 |  |  | 	// XXX add support for offloading the processing to a thread/worker...
 | 
					
						
							| 
									
										
										
										
											2020-11-02 05:33:29 +03:00
										 |  |  | 	// XXX would be nice to be able to abort this...
 | 
					
						
							|  |  |  | 	// 		...and/or have a generic abort protocol triggered when loading...
 | 
					
						
							| 
									
										
										
										
											2020-11-03 04:49:56 +03:00
										 |  |  | 	// 		...use task queue???
 | 
					
						
							| 
									
										
										
										
											2020-11-02 05:33:29 +03:00
										 |  |  | 	// XXX make each section optional...
 | 
					
						
							| 
									
										
										
										
											2020-11-05 06:31:13 +03:00
										 |  |  | 	cacheMetadata: ['- Sharp|Image/', | 
					
						
							|  |  |  | 		core.doc`Cache metadata
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			Cache metadata for current image... | 
					
						
							|  |  |  | 			.cacheMetadata() | 
					
						
							|  |  |  | 			.cacheMetadata('current') | 
					
						
							|  |  |  | 				-> promise([ gid | null ]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			Force cache metadata for current image... | 
					
						
							|  |  |  | 			.cacheMetadata(true) | 
					
						
							|  |  |  | 			.cacheMetadata('current', true) | 
					
						
							|  |  |  | 				-> promise([ gid | null ]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			Cache metadata for all images... | 
					
						
							|  |  |  | 			.cacheMetadata('all') | 
					
						
							|  |  |  | 				-> promise([ gid | null, .. ]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			Force cache metadata for all images... | 
					
						
							|  |  |  | 			.cacheMetadata('all', true) | 
					
						
							|  |  |  | 				-> promise([ gid | null, .. ]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			Cache metadata for specific images... | 
					
						
							|  |  |  | 			.cacheMetadata([ gid, .. ]) | 
					
						
							|  |  |  | 				-> promise([ gid | null, .. ]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			Force cache metadata for specific images... | 
					
						
							|  |  |  | 			.cacheMetadata([ gid, .. ], true) | 
					
						
							|  |  |  | 				-> promise([ gid | null, .. ]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		NOTE: this will effectively update metadata format to the new spec... | 
					
						
							| 
									
										
										
										
											2020-11-02 05:33:29 +03:00
										 |  |  | 		`,
 | 
					
						
							| 
									
										
										
										
											2020-11-02 03:16:01 +03:00
										 |  |  | 		function(images, logger){ | 
					
						
							|  |  |  | 			var that = this | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-05 06:31:13 +03:00
										 |  |  | 			// handle logging and processing list...
 | 
					
						
							|  |  |  | 			// NOTE: these will maintain .__metadata_reading helping 
 | 
					
						
							|  |  |  | 			// 		avoid processing an image more than once at the same 
 | 
					
						
							|  |  |  | 			// 		time...
 | 
					
						
							|  |  |  | 			var done = function(gid, msg){ | 
					
						
							|  |  |  | 				logger && logger.emit(msg || 'done', gid) | 
					
						
							|  |  |  | 				if(that.__metadata_reading){ | 
					
						
							|  |  |  | 					that.__metadata_reading.delete(gid)  | 
					
						
							|  |  |  | 					if(that.__metadata_reading.size == 0){ | 
					
						
							|  |  |  | 						delete that.__metadata_reading } } | 
					
						
							|  |  |  | 				return gid } | 
					
						
							|  |  |  | 			var skipping = function(gid){ | 
					
						
							|  |  |  | 				return done(gid, 'skipping') } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			var force = false | 
					
						
							|  |  |  | 			if(images === true){ | 
					
						
							|  |  |  | 				force = true | 
					
						
							|  |  |  | 				images = null | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			} else if(logger === true){ | 
					
						
							|  |  |  | 				force = true | 
					
						
							|  |  |  | 				logger = arguments[2] } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// NOTE: we are caching this to avoid messing things up when 
 | 
					
						
							|  |  |  | 			// 		loading before this was finished...
 | 
					
						
							|  |  |  | 			var cached_images = this.images | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-02 03:16:01 +03:00
										 |  |  | 			// get/normalize images...
 | 
					
						
							|  |  |  | 			//images = images || this.current
 | 
					
						
							|  |  |  | 			images = images  | 
					
						
							|  |  |  | 				|| 'current' | 
					
						
							|  |  |  | 			// keywords...
 | 
					
						
							|  |  |  | 			images =  | 
					
						
							|  |  |  | 				images == 'all' ?  | 
					
						
							|  |  |  | 					this.data.getImages('all') | 
					
						
							|  |  |  | 				: images == 'loaded' ? | 
					
						
							|  |  |  | 					(this.ribbons ? | 
					
						
							|  |  |  | 						this.ribbons.getImageGIDs() | 
					
						
							|  |  |  | 						: this.data.getImages('all')) | 
					
						
							|  |  |  | 				: images == 'current' ?  | 
					
						
							|  |  |  | 					this.current | 
					
						
							|  |  |  | 				: images | 
					
						
							| 
									
										
										
										
											2020-11-05 06:31:13 +03:00
										 |  |  | 			images = (images instanceof Array ?  | 
					
						
							|  |  |  | 					images  | 
					
						
							|  |  |  | 					: [images]) | 
					
						
							|  |  |  | 				.filter(function(gid){ | 
					
						
							|  |  |  | 					return !that.__metadata_reading | 
					
						
							|  |  |  | 						|| !that.__metadata_reading.has(gid) }) | 
					
						
							| 
									
										
										
										
											2020-11-02 03:16:01 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			logger = logger !== false ? | 
					
						
							|  |  |  | 				(logger || this.logger) | 
					
						
							|  |  |  | 				: false | 
					
						
							|  |  |  | 			logger = logger && logger.push('Caching image metadata') | 
					
						
							|  |  |  | 			logger && logger.emit('queued', images) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-02 06:06:42 +03:00
										 |  |  | 			/*/ XXX set this to tmp for .location.load =='loadImages' | 
					
						
							| 
									
										
										
										
											2020-11-02 17:11:42 +03:00
										 |  |  | 			// XXX add preview cache directory...
 | 
					
						
							|  |  |  | 			// 		- user defined path
 | 
					
						
							|  |  |  | 			// 		- cleanable 
 | 
					
						
							|  |  |  | 			// 			partially (remove orphans) / full...
 | 
					
						
							|  |  |  | 			// 		- not sure how to index...
 | 
					
						
							| 
									
										
										
										
											2020-11-02 06:06:42 +03:00
										 |  |  | 			var base_path = that.location.load == 'loadIndex' ? | 
					
						
							|  |  |  | 				null | 
					
						
							|  |  |  | 				: tmp | 
					
						
							|  |  |  | 			/*/ | 
					
						
							|  |  |  | 			var base_path | 
					
						
							|  |  |  | 			//*/
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-02 03:16:01 +03:00
										 |  |  | 			return images | 
					
						
							|  |  |  | 				.mapChunks(function(gid){ | 
					
						
							| 
									
										
										
										
											2020-11-05 06:31:13 +03:00
										 |  |  | 					var img = cached_images[gid] | 
					
						
							|  |  |  | 					var path = img && that.getImagePath(gid) | 
					
						
							|  |  |  | 					;(that.__metadata_reading =  | 
					
						
							|  |  |  | 							that.__metadata_reading || new Set()) | 
					
						
							|  |  |  | 						.add(gid) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					// skip...
 | 
					
						
							|  |  |  | 					if(!(img && path | 
					
						
							|  |  |  | 							&& (force | 
					
						
							|  |  |  | 								// high priority must be preset...
 | 
					
						
							|  |  |  | 								|| (img.orientation == null | 
					
						
							|  |  |  | 									&& img.flipped == null) | 
					
						
							|  |  |  | 								// update metadata...
 | 
					
						
							|  |  |  | 								|| (img.metadata || {}).ImageGridMetadata == null))){ | 
					
						
							|  |  |  | 						skipping(gid) | 
					
						
							|  |  |  | 						return } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-02 03:16:01 +03:00
										 |  |  | 					return sharp(that.getImagePath(gid)) | 
					
						
							|  |  |  | 						.metadata() | 
					
						
							| 
									
										
										
										
											2020-11-02 05:33:29 +03:00
										 |  |  | 						.catch(function(){ | 
					
						
							| 
									
										
										
										
											2020-11-05 06:31:13 +03:00
										 |  |  | 							skipping(gid) }) | 
					
						
							| 
									
										
										
										
											2020-11-02 05:33:29 +03:00
										 |  |  | 						.then(function(metadata){ | 
					
						
							| 
									
										
										
										
											2020-11-05 06:31:13 +03:00
										 |  |  | 							// no metadata...
 | 
					
						
							| 
									
										
										
										
											2020-11-02 05:33:29 +03:00
										 |  |  | 							if(metadata == null){ | 
					
						
							| 
									
										
										
										
											2020-11-05 06:31:13 +03:00
										 |  |  | 								skipping(gid) | 
					
						
							| 
									
										
										
										
											2020-11-02 05:33:29 +03:00
										 |  |  | 								return } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 							var o = normalizeOrientation(metadata.orientation) | 
					
						
							| 
									
										
										
										
											2020-11-05 06:31:13 +03:00
										 |  |  | 							;(force || img.orientation == null) | 
					
						
							|  |  |  | 								// NOTE: we need to set orientation to something
 | 
					
						
							|  |  |  | 								// 		or we'll check it again and again...
 | 
					
						
							|  |  |  | 								&& (img.orientation = o.orientation || 0) | 
					
						
							|  |  |  | 							;(force || img.flipped == null) | 
					
						
							|  |  |  | 								&& (img.flipped = o.flipped) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 							// mark metadata as partially read...
 | 
					
						
							|  |  |  | 							// NOTE: this will intentionally overwrite the 
 | 
					
						
							|  |  |  | 							// 		previous reader mark/mode...
 | 
					
						
							|  |  |  | 							img.metadata = | 
					
						
							|  |  |  | 								Object.assign( | 
					
						
							|  |  |  | 									img.metadata || {},  | 
					
						
							|  |  |  | 									{  | 
					
						
							|  |  |  | 										ImageGridMetadataReader: 'sharp/exif-reader/ImageGrid', | 
					
						
							|  |  |  | 										// mark metadata as partial read...
 | 
					
						
							|  |  |  | 										// NOTE: partial metadata will get reread by 
 | 
					
						
							|  |  |  | 										// 		the metadata feature upon request...
 | 
					
						
							|  |  |  | 										ImageGridMetadata: 'partial',  | 
					
						
							|  |  |  | 									}) | 
					
						
							| 
									
										
										
										
											2020-11-02 03:16:01 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-03 04:49:56 +03:00
										 |  |  | 							// read the metadata...
 | 
					
						
							|  |  |  | 							var exif = metadata.exif  | 
					
						
							|  |  |  | 								&& exifReader(metadata.exif)  | 
					
						
							|  |  |  | 							exif | 
					
						
							|  |  |  | 								&& Object.assign( | 
					
						
							| 
									
										
										
										
											2020-11-05 06:31:13 +03:00
										 |  |  | 									img.metadata,  | 
					
						
							|  |  |  | 									exifReader2exiftool(exif)) | 
					
						
							| 
									
										
										
										
											2020-11-03 04:49:56 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-02 05:33:29 +03:00
										 |  |  | 							// if image too large, generate preview(s)...
 | 
					
						
							| 
									
										
										
										
											2020-11-02 17:11:42 +03:00
										 |  |  | 							// XXX EXPERIMENTAL...
 | 
					
						
							| 
									
										
										
										
											2020-11-02 05:33:29 +03:00
										 |  |  | 							var size_threshold = that.config['preview-generate-threshold'] | 
					
						
							|  |  |  | 							if(size_threshold | 
					
						
							| 
									
										
										
										
											2020-11-02 06:06:42 +03:00
										 |  |  | 									&& img.preview == null | 
					
						
							| 
									
										
										
										
											2020-11-02 05:33:29 +03:00
										 |  |  | 									&& Math.max(metadata.width, metadata.height) > size_threshold){ | 
					
						
							|  |  |  | 								logger && logger.emit('Image too large', gid) | 
					
						
							| 
									
										
										
										
											2020-11-02 06:06:42 +03:00
										 |  |  | 								// XXX make this more generic...
 | 
					
						
							|  |  |  | 								// 		...if 'loadImages' should create previews in tmp...
 | 
					
						
							|  |  |  | 								that.location.load == 'loadIndex' | 
					
						
							|  |  |  | 									&& that.makePreviews(gid,  | 
					
						
							|  |  |  | 										that.config['preview-sizes-priority'] || 1080, | 
					
						
							|  |  |  | 										base_path, | 
					
						
							|  |  |  | 										logger) } | 
					
						
							| 
									
										
										
										
											2020-11-02 05:33:29 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-05 06:31:13 +03:00
										 |  |  | 							that.markChanged | 
					
						
							|  |  |  | 								&& that.markChanged('images', [gid]) | 
					
						
							|  |  |  | 							that.ribbons | 
					
						
							| 
									
										
										
										
											2020-11-02 05:33:29 +03:00
										 |  |  | 								&& that.ribbons.updateImage(gid)  | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-05 06:31:13 +03:00
										 |  |  | 							return done(gid) }) }) }], | 
					
						
							|  |  |  | 	cacheAllMetadata: ['- Sharp|Image/', | 
					
						
							|  |  |  | 		core.doc`Cache all metadata
 | 
					
						
							|  |  |  | 		NOTE: this is a shorthand to .cacheMetadata('all', ..)`,
 | 
					
						
							|  |  |  | 		'cacheMetadata: "all" ...'], | 
					
						
							| 
									
										
										
										
											2016-05-22 21:10:37 +03:00
										 |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-26 05:36:28 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | // XXX need to auto-generate previews for very large images...
 | 
					
						
							| 
									
										
										
										
											2016-05-22 21:10:37 +03:00
										 |  |  | var Sharp =  | 
					
						
							|  |  |  | module.Sharp = core.ImageGridFeatures.Feature({ | 
					
						
							|  |  |  | 	title: '', | 
					
						
							|  |  |  | 	doc: '', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	tag: 'sharp', | 
					
						
							|  |  |  | 	depends: [ | 
					
						
							|  |  |  | 		'location', | 
					
						
							| 
									
										
										
										
											2016-05-26 05:36:28 +03:00
										 |  |  | 		'index-format', | 
					
						
							| 
									
										
										
										
											2016-05-22 21:10:37 +03:00
										 |  |  | 	], | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	actions: SharpActions,  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	isApplicable: function(){ return !!sharp }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	handlers: [ | 
					
						
							| 
									
										
										
										
											2020-11-04 18:02:27 +03:00
										 |  |  | 		/* XXX this needs to be run in the background... | 
					
						
							|  |  |  | 		// XXX this is best done in a thread + needs to be abortable (on .load(..))...
 | 
					
						
							| 
									
										
										
										
											2020-11-02 03:16:01 +03:00
										 |  |  | 		['loadImages', | 
					
						
							|  |  |  | 			function(){ | 
					
						
							| 
									
										
										
										
											2020-11-05 06:31:13 +03:00
										 |  |  | 				this.cacheMetadata('all') }], | 
					
						
							| 
									
										
										
										
											2020-11-02 03:16:01 +03:00
										 |  |  | 		//*/
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-03 04:46:51 +03:00
										 |  |  | 		// set orientation if not defined...
 | 
					
						
							| 
									
										
										
										
											2020-11-02 05:33:29 +03:00
										 |  |  | 		// NOTE: progress on this is not shown so as to avoid spamming 
 | 
					
						
							|  |  |  | 		// 		the UI...
 | 
					
						
							|  |  |  | 		// XXX should this be pre or post???
 | 
					
						
							|  |  |  | 		// 		...creating a preview would be more logical than trying 
 | 
					
						
							|  |  |  | 		// 		to load a gigantic image, maybe even loading a placeholder
 | 
					
						
							|  |  |  | 		// 		while doing so...
 | 
					
						
							|  |  |  | 		//['updateImage.pre',
 | 
					
						
							|  |  |  | 		//	function(gid){
 | 
					
						
							| 
									
										
										
										
											2016-06-03 04:46:51 +03:00
										 |  |  | 		['updateImage', | 
					
						
							|  |  |  | 			function(_, gid){ | 
					
						
							| 
									
										
										
										
											2020-11-05 06:31:13 +03:00
										 |  |  | 				var that = this | 
					
						
							|  |  |  | 				this.cacheMetadata(gid, false)  | 
					
						
							|  |  |  | 					.then(function([res]){ | 
					
						
							|  |  |  | 						res  | 
					
						
							|  |  |  | 							&& that.logger  | 
					
						
							|  |  |  | 								&& that.logger.emit('Cached metadata for', gid) }) }], | 
					
						
							| 
									
										
										
										
											2016-06-03 04:46:51 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-22 23:11:12 +03:00
										 |  |  | 		// XXX need to:
 | 
					
						
							|  |  |  | 		// 		- if image too large to set the preview to "loading..."
 | 
					
						
							|  |  |  | 		// 		- create previews...
 | 
					
						
							|  |  |  | 		// 		- update image...
 | 
					
						
							| 
									
										
										
										
											2016-05-23 03:42:53 +03:00
										 |  |  | 		/* | 
					
						
							| 
									
										
										
										
											2016-05-22 21:10:37 +03:00
										 |  |  | 		['updateImage.pre', | 
					
						
							|  |  |  | 			function(gid){ | 
					
						
							|  |  |  | 				var that = this | 
					
						
							|  |  |  | 				if(this.images[gid].preview == null){ | 
					
						
							|  |  |  | 					sharp(this.getImagePath(gid)) | 
					
						
							|  |  |  | 						.metadata() | 
					
						
							|  |  |  | 						.then(function(metadata){ | 
					
						
							| 
									
										
										
										
											2016-05-22 23:11:12 +03:00
										 |  |  | 							// current image is larger than any of the previews...
 | 
					
						
							| 
									
										
										
										
											2016-05-22 21:10:37 +03:00
										 |  |  | 							if(Math.max(metadata.width, metadata.height)  | 
					
						
							|  |  |  | 									> Math.max.apply(Math, that.config['preview-sizes'])){ | 
					
						
							| 
									
										
										
										
											2016-05-22 23:11:12 +03:00
										 |  |  | 								// create the currently needed preview first...
 | 
					
						
							|  |  |  | 								that.makePreviews(gid, that.ribbons.getVisibleImageSize()) | 
					
						
							|  |  |  | 									.then(function(){ | 
					
						
							|  |  |  | 										// load the created preview...
 | 
					
						
							|  |  |  | 										that.ribbons.updateImage(gid) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 										// create the rest...
 | 
					
						
							|  |  |  | 										that.makePreviews(gid) | 
					
						
							|  |  |  | 									}) | 
					
						
							| 
									
										
										
										
											2016-05-22 21:10:37 +03:00
										 |  |  | 							} | 
					
						
							|  |  |  | 						}) | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			}] | 
					
						
							| 
									
										
										
										
											2016-05-23 03:42:53 +03:00
										 |  |  | 		//*/
 | 
					
						
							| 
									
										
										
										
											2016-05-22 21:10:37 +03:00
										 |  |  | 	], | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /********************************************************************** | 
					
						
							| 
									
										
										
										
											2016-08-20 22:49:36 +03:00
										 |  |  | * vim:set ts=4 sw=4 :                               */ return module }) |