| 
									
										
										
										
											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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-17 23:19:42 +03:00
										 |  |  | var runner = require('lib/types/runner') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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', | 
					
						
							| 
									
										
										
										
											2020-11-29 16:52:22 +03:00
										 |  |  | 	'exif.FNumber': [ | 
					
						
							|  |  |  | 		'fNumber',  | 
					
						
							|  |  |  | 		function(v){  | 
					
						
							|  |  |  | 			return 'f/'+v }], | 
					
						
							|  |  |  | 	'exif.ExposureTime': [ | 
					
						
							|  |  |  | 		'exposureTime', | 
					
						
							| 
									
										
										
										
											2020-11-03 04:49:56 +03:00
										 |  |  | 		// 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...
 | 
					
						
							| 
									
										
										
										
											2020-11-29 16:52:22 +03:00
										 |  |  | 	'exif.DateTimeOriginal': [ | 
					
						
							|  |  |  | 		'date/timeOriginal', | 
					
						
							| 
									
										
										
										
											2020-11-03 04:49:56 +03:00
										 |  |  | 		function(v){ | 
					
						
							|  |  |  | 			return v.toShortDate() }], | 
					
						
							| 
									
										
										
										
											2020-11-29 16:52:22 +03:00
										 |  |  | 	'image.ModifyDate': [ | 
					
						
							|  |  |  | 		'modifyDate',  | 
					
						
							| 
									
										
										
										
											2020-11-03 04:49:56 +03:00
										 |  |  | 		'exif.DateTimeOriginal'], | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// IPCT...
 | 
					
						
							|  |  |  | 	'image.Artist': 'artist', | 
					
						
							|  |  |  | 	'image.Copyright': 'copyright', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// XXX anything else???
 | 
					
						
							| 
									
										
										
										
											2020-11-02 03:16:01 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-10 17:48:44 +03:00
										 |  |  | // NOTE: this only reads the .rating from xmp...
 | 
					
						
							| 
									
										
										
										
											2020-11-03 04:49:56 +03:00
										 |  |  | var exifReader2exiftool =  | 
					
						
							|  |  |  | module.exifReader2exiftool = | 
					
						
							| 
									
										
										
										
											2020-11-10 17:48:44 +03:00
										 |  |  | function(exif, xmp){ | 
					
						
							| 
									
										
										
										
											2020-11-03 04:49:56 +03:00
										 |  |  | 	return Object.entries(EXIF_FORMAT) | 
					
						
							| 
									
										
										
										
											2020-11-10 17:48:44 +03:00
										 |  |  | 		// handle exif...
 | 
					
						
							| 
									
										
										
										
											2020-11-03 04:49:56 +03:00
										 |  |  | 		.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){  | 
					
						
							| 
									
										
										
										
											2020-11-10 17:48:44 +03:00
										 |  |  | 					return res && res[e] }, exif) | 
					
						
							| 
									
										
										
										
											2020-11-03 04:49:56 +03:00
										 |  |  | 			// set the value...
 | 
					
						
							|  |  |  | 			if(value !== undefined){ | 
					
						
							|  |  |  | 				res[to] = handler ? | 
					
						
							|  |  |  | 					handler(value) | 
					
						
							|  |  |  | 					: value } | 
					
						
							|  |  |  | 			return res }, {}) | 
					
						
							|  |  |  | 		// handle xmp...
 | 
					
						
							|  |  |  | 		.run(function(){ | 
					
						
							| 
									
										
										
										
											2020-11-10 17:48:44 +03:00
										 |  |  | 			var rating = xmp  | 
					
						
							| 
									
										
										
										
											2020-11-03 04:49:56 +03:00
										 |  |  | 				// NOTE: we do not need the full XML 
 | 
					
						
							|  |  |  | 				// 		fluff here, just get some values...
 | 
					
						
							|  |  |  | 				&& parseInt( | 
					
						
							| 
									
										
										
										
											2020-11-10 17:48:44 +03:00
										 |  |  | 					(xmp.toString() | 
					
						
							| 
									
										
										
										
											2020-11-03 04:49:56 +03:00
										 |  |  | 							.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-12-06 04:39:42 +03:00
										 |  |  | 	// XXX revise return values...
 | 
					
						
							| 
									
										
										
										
											2020-10-30 19:16:42 +03:00
										 |  |  | 	// XXX make backup name pattern configurable...
 | 
					
						
							| 
									
										
										
										
											2020-12-06 04:39:42 +03:00
										 |  |  | 	// XXX CROP ready for crop support...
 | 
					
						
							| 
									
										
										
										
											2020-12-17 18:57:14 +03:00
										 |  |  | 	makeResizedImage: ['- Image/', | 
					
						
							|  |  |  | 		core.doc`Make resized image(s)...
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			.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 / name pattern...
 | 
					
						
							|  |  |  | 				//
 | 
					
						
							|  |  |  | 				// NOTE: for multiple images this should be a pattern and not an
 | 
					
						
							|  |  |  | 				// 		explicit name...
 | 
					
						
							|  |  |  | 				// NOTE: if not given this defaults to: "%n"
 | 
					
						
							|  |  |  | 				name: null | <str>, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// image name pattern data...
 | 
					
						
							|  |  |  | 				//
 | 
					
						
							|  |  |  | 				// NOTE: for more info on pattern see: .formatImageName(..)
 | 
					
						
							|  |  |  | 				data: null | { .. }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// if true and image is smaller than size enlarge it...
 | 
					
						
							|  |  |  | 				// 
 | 
					
						
							|  |  |  | 				// default: null / false
 | 
					
						
							|  |  |  | 				enlarge: null | true, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// overwrite, backup or skip (default) existing images...
 | 
					
						
							|  |  |  | 				//
 | 
					
						
							|  |  |  | 				// default: null / false
 | 
					
						
							|  |  |  | 				overwrite: null | true | 'backup', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// if true do not write an image if it's smaller than size...
 | 
					
						
							|  |  |  | 				// 
 | 
					
						
							|  |  |  | 				// default: null / false
 | 
					
						
							|  |  |  | 				skipSmaller: null | true, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// XXX not implemented...
 | 
					
						
							|  |  |  | 				transform: ..., | 
					
						
							|  |  |  | 				crop: ..., | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				timestamp: ..., | 
					
						
							|  |  |  | 				logger: ..., | 
					
						
							|  |  |  | ,			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		NOTE: all options are optional. | 
					
						
							|  |  |  | 		NOTE: this will not overwrite existing images. | 
					
						
							| 
									
										
										
										
											2020-12-15 05:36:37 +03:00
										 |  |  | 		`,
 | 
					
						
							|  |  |  | 		core.queueHandler('Making resized image',  | 
					
						
							|  |  |  | 			// prepare the data for image resizing (session queue)...
 | 
					
						
							|  |  |  | 			core.sessionQueueHandler('Gathering image data for resizing',  | 
					
						
							|  |  |  | 				// prepare the input index-dependant data in a fast way...
 | 
					
						
							| 
									
										
										
										
											2020-12-17 18:57:14 +03:00
										 |  |  | 				function(queue, _, images, size, path, options){ | 
					
						
							| 
									
										
										
										
											2020-12-17 20:14:39 +03:00
										 |  |  | 					var args = [...arguments].slice(2) | 
					
						
							| 
									
										
										
										
											2020-12-17 18:57:14 +03:00
										 |  |  | 					if(queue == 'sync'){ | 
					
						
							| 
									
										
										
										
											2020-12-17 20:14:39 +03:00
										 |  |  | 						args.unshift(_) | 
					
						
							|  |  |  | 						var [images, size, path, options] = args } | 
					
						
							| 
									
										
										
										
											2020-12-15 05:36:37 +03:00
										 |  |  | 					// sanity check...
 | 
					
						
							| 
									
										
										
										
											2020-12-17 20:14:39 +03:00
										 |  |  | 					if(args.length < 3){ | 
					
						
							| 
									
										
										
										
											2020-12-15 05:36:37 +03:00
										 |  |  | 						throw new Error('.makeResizedImage(..): ' | 
					
						
							|  |  |  | 							+'need at least: images, size and path.') } | 
					
						
							|  |  |  | 					return [ | 
					
						
							|  |  |  | 						(images == null || images == 'all') ?  | 
					
						
							|  |  |  | 								this.data.getImages('all') | 
					
						
							|  |  |  | 							: images == 'current' ?  | 
					
						
							|  |  |  | 								[this.current] | 
					
						
							|  |  |  | 							: images instanceof Array ?  | 
					
						
							|  |  |  | 								images  | 
					
						
							|  |  |  | 							: [images], | 
					
						
							| 
									
										
										
										
											2020-12-17 20:14:39 +03:00
										 |  |  | 						...args.slice(1), | 
					
						
							| 
									
										
										
										
											2020-12-15 05:36:37 +03:00
										 |  |  | 					]}, | 
					
						
							|  |  |  | 				// prepare index independent data, this can be a tad slow...
 | 
					
						
							| 
									
										
										
										
											2020-12-17 23:19:42 +03:00
										 |  |  | 				function(gid, _, path, options={}){ | 
					
						
							|  |  |  | 					// special case: we already got the paths...
 | 
					
						
							|  |  |  | 					if(gid instanceof Array){ | 
					
						
							|  |  |  | 						return gid } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-15 05:36:37 +03:00
										 |  |  | 					var image = this.images[gid] | 
					
						
							|  |  |  | 					// options...
 | 
					
						
							|  |  |  | 					var { | 
					
						
							|  |  |  | 						name,  | 
					
						
							|  |  |  | 						data,  | 
					
						
							|  |  |  | 					} = options || {} | 
					
						
							|  |  |  | 					name = name || '%n' | 
					
						
							|  |  |  | 					// skip non-images...
 | 
					
						
							|  |  |  | 					if(!image || !['image', null, undefined] | 
					
						
							|  |  |  | 							.includes(image.type)){ | 
					
						
							| 
									
										
										
										
											2020-12-17 18:57:14 +03:00
										 |  |  | 						return runner.SKIP } | 
					
						
							| 
									
										
										
										
											2020-12-15 05:36:37 +03:00
										 |  |  | 					return [ | 
					
						
							|  |  |  | 						// source...
 | 
					
						
							|  |  |  | 						this.getImagePath(gid), | 
					
						
							|  |  |  | 						// target...
 | 
					
						
							|  |  |  | 						pathlib.resolve( | 
					
						
							|  |  |  | 							this.location.path, | 
					
						
							|  |  |  | 							pathlib.join( | 
					
						
							|  |  |  | 								path,  | 
					
						
							|  |  |  | 								// if name is not a pattern do not re-format it...
 | 
					
						
							|  |  |  | 								name.includes('%') ? | 
					
						
							|  |  |  | 									this.formatImageName(name, gid, data || {}) | 
					
						
							|  |  |  | 									: name)), | 
					
						
							|  |  |  | 						// image data...
 | 
					
						
							|  |  |  | 						// note: we include only the stuff we need...
 | 
					
						
							|  |  |  | 						{ | 
					
						
							|  |  |  | 							orientation: image.orientation, | 
					
						
							|  |  |  | 							flipped: image.flipped, | 
					
						
							|  |  |  | 							// crop...
 | 
					
						
							|  |  |  | 						}, | 
					
						
							|  |  |  | 					] }), | 
					
						
							|  |  |  | 			// do the actual resizing (global queue)...
 | 
					
						
							| 
									
										
										
										
											2020-12-17 23:19:42 +03:00
										 |  |  | 			function([source, to, image={}], size, _, options={}){ | 
					
						
							| 
									
										
										
										
											2020-12-17 18:57:14 +03:00
										 |  |  | 				// handle skipped items -- source, to and image are undefined...
 | 
					
						
							|  |  |  | 				if(source == null){ | 
					
						
							|  |  |  | 					return undefined } | 
					
						
							| 
									
										
										
										
											2020-12-15 05:36:37 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				// sizing...
 | 
					
						
							|  |  |  | 				var fit =  | 
					
						
							|  |  |  | 					typeof(size) == typeof('str') ? | 
					
						
							|  |  |  | 						(size.endsWith('px') ? | 
					
						
							|  |  |  | 							'inside' | 
					
						
							|  |  |  | 						: size.endsWith('p') ? | 
					
						
							|  |  |  | 							'outside' | 
					
						
							|  |  |  | 						: 'inside') | 
					
						
							|  |  |  | 					: 'inside' | 
					
						
							|  |  |  | 				size = parseInt(size) | 
					
						
							|  |  |  | 				// options...
 | 
					
						
							|  |  |  | 				var { | 
					
						
							|  |  |  | 					enlarge, | 
					
						
							|  |  |  | 					skipSmaller, | 
					
						
							|  |  |  | 					overwrite, | 
					
						
							|  |  |  | 					transform,  | 
					
						
							|  |  |  | 					timestamp, | 
					
						
							|  |  |  | 					backupImagePattern, | 
					
						
							|  |  |  | 					//logger, 
 | 
					
						
							|  |  |  | 				} = options | 
					
						
							|  |  |  | 				// defaults...
 | 
					
						
							|  |  |  | 				transform = transform === undefined ?  | 
					
						
							|  |  |  | 					true  | 
					
						
							|  |  |  | 					: transform | 
					
						
							|  |  |  | 				timestamp = timestamp || Date.timeStamp() | 
					
						
							|  |  |  | 				// backup by default...
 | 
					
						
							|  |  |  | 				overwrite = overwrite === undefined ?  | 
					
						
							|  |  |  | 					'backup'  | 
					
						
							|  |  |  | 					: overwrite | 
					
						
							|  |  |  | 				backupImagePattern =  | 
					
						
							|  |  |  | 					(backupImagePattern  | 
					
						
							|  |  |  | 						|| '${PATH}.${TIMESTAMP}${COUNT}.bak') | 
					
						
							|  |  |  | 					.replace(/\${PATH}|$PATH/, to) | 
					
						
							|  |  |  | 					.replace(/\${TIMESTAMP}|$TIMESTAMP/, timestamp) | 
					
						
							|  |  |  | 				// backup...
 | 
					
						
							|  |  |  | 				// NOTE: we are doing the check at the very last moment and 
 | 
					
						
							|  |  |  | 				// 		not here to avoid race conditions as much as practical...
 | 
					
						
							|  |  |  | 				var backupName = function(){ | 
					
						
							|  |  |  | 					var i = 0 | 
					
						
							|  |  |  | 					var n | 
					
						
							|  |  |  | 					do{ | 
					
						
							|  |  |  | 						n = backupImagePattern | 
					
						
							|  |  |  | 							.replace(/\${COUNT}|$COUNT/, i++ ? '.'+i : i) | 
					
						
							|  |  |  | 					} while(fse.existsSync(n)) | 
					
						
							|  |  |  | 					return n } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				var img = sharp(source) | 
					
						
							|  |  |  | 				return (skipSmaller ? | 
					
						
							|  |  |  | 						// skip if smaller than size...
 | 
					
						
							|  |  |  | 						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)){ | 
					
						
							|  |  |  | 									return } | 
					
						
							|  |  |  | 								// continue...
 | 
					
						
							|  |  |  | 								return img }) | 
					
						
							|  |  |  | 						: Promise.resolve(img)) | 
					
						
							|  |  |  | 					// prepare to write...
 | 
					
						
							|  |  |  | 					.then(function(img){ | 
					
						
							|  |  |  | 						return img  | 
					
						
							|  |  |  | 							&& ensureDir(pathlib.dirname(to)) | 
					
						
							|  |  |  | 								.then(function(){ | 
					
						
							|  |  |  | 									// handle existing image...
 | 
					
						
							|  |  |  | 									if(fse.existsSync(to)){ | 
					
						
							|  |  |  | 										// rename...
 | 
					
						
							|  |  |  | 										if(overwrite == 'backup'){ | 
					
						
							|  |  |  | 											fse.renameSync(to, backupName(to)) | 
					
						
							|  |  |  | 										// remove...
 | 
					
						
							|  |  |  | 										} else if(overwrite){ | 
					
						
							|  |  |  | 											fse.removeSync(to) | 
					
						
							|  |  |  | 										// skip...
 | 
					
						
							|  |  |  | 										} else { | 
					
						
							|  |  |  | 											return Promise.reject('target exists') } } | 
					
						
							|  |  |  | 									// write...
 | 
					
						
							|  |  |  | 									return img | 
					
						
							|  |  |  | 										.clone() | 
					
						
							|  |  |  | 										// handle transform (.orientation / .flip) and .crop...
 | 
					
						
							|  |  |  | 										.run(function(){ | 
					
						
							|  |  |  | 											if(transform && (image.orientation || image.flipped)){ | 
					
						
							|  |  |  | 												image.orientation | 
					
						
							|  |  |  | 													&& this.rotate(image.orientation) | 
					
						
							|  |  |  | 												image.flipped | 
					
						
							|  |  |  | 													&& image.flipped.includes('horizontal') | 
					
						
							|  |  |  | 													&& this.flip() } | 
					
						
							|  |  |  | 												image.flipped | 
					
						
							|  |  |  | 													&& image.flipped.includes('vertical') | 
					
						
							|  |  |  | 													&& this.flop()  | 
					
						
							|  |  |  | 											// XXX CROP
 | 
					
						
							|  |  |  | 											//if(crop){
 | 
					
						
							|  |  |  | 											//	// XXX
 | 
					
						
							|  |  |  | 											//}
 | 
					
						
							|  |  |  | 										}) | 
					
						
							|  |  |  | 										.resize({ | 
					
						
							|  |  |  | 											width: size, | 
					
						
							|  |  |  | 											height: size, | 
					
						
							|  |  |  | 											fit: fit, | 
					
						
							|  |  |  | 											withoutEnlargement: !enlarge, | 
					
						
							| 
									
										
										
										
											2020-12-06 04:39:42 +03:00
										 |  |  | 										}) | 
					
						
							|  |  |  | 										.withMetadata() | 
					
						
							|  |  |  | 										.toFile(to)  | 
					
						
							|  |  |  | 										.then(function(){ | 
					
						
							|  |  |  | 											// XXX what should we return???
 | 
					
						
							|  |  |  | 											return to }) }) }) })], | 
					
						
							| 
									
										
										
										
											2020-10-31 05:10:51 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-17 23:19:42 +03:00
										 |  |  | 	// XXX should we split this into a session and global versions 
 | 
					
						
							|  |  |  | 	// 		a-la .makeResizedImage(..)???
 | 
					
						
							| 
									
										
										
										
											2020-11-01 15:24:22 +03:00
										 |  |  | 	// XXX this does not update image.base_path -- is this correct???
 | 
					
						
							| 
									
										
										
										
											2020-12-17 20:14:39 +03:00
										 |  |  | 	// XXX make index dir hidden...
 | 
					
						
							| 
									
										
										
										
											2020-11-01 15:24:22 +03:00
										 |  |  | 	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-12-07 03:00:20 +03:00
										 |  |  | 		NOTE: currently this is a core.sessionQueueHandler(..) and not a .queueHandler(..) | 
					
						
							|  |  |  | 			mainly because we need to add the preview refs back to the index and this | 
					
						
							|  |  |  | 			would need keeping the index in memory even if we loaded a different index, | 
					
						
							|  |  |  | 			this is possible but needs more thought. | 
					
						
							| 
									
										
										
										
											2020-11-01 15:24:22 +03:00
										 |  |  | 		`,
 | 
					
						
							| 
									
										
										
										
											2020-12-07 03:00:20 +03:00
										 |  |  | 		core.sessionQueueHandler('Make image previews',  | 
					
						
							| 
									
										
										
										
											2020-12-06 19:09:06 +03:00
										 |  |  | 			function(queue, images, ...args){ | 
					
						
							|  |  |  | 				// get/normalize images...
 | 
					
						
							|  |  |  | 				return [ | 
					
						
							|  |  |  | 					(images == null || images == 'all') ?  | 
					
						
							|  |  |  | 							this.data.getImages('all') | 
					
						
							|  |  |  | 						: images == 'current' ?  | 
					
						
							|  |  |  | 							[this.current] | 
					
						
							|  |  |  | 						: images instanceof Array ?  | 
					
						
							|  |  |  | 							images  | 
					
						
							|  |  |  | 						: [images], | 
					
						
							|  |  |  | 					...args, | 
					
						
							|  |  |  | 				] }, | 
					
						
							|  |  |  | 			function(gid, sizes, base_path, logger){ | 
					
						
							|  |  |  | 				var that = this | 
					
						
							| 
									
										
										
										
											2020-11-01 15:24:22 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-06 19:09:06 +03:00
										 |  |  | 				var logger_mode = this.config['preview-progress-mode'] || 'gids' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// 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 } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-17 20:14:39 +03:00
										 |  |  | 				// partially fill in the template...
 | 
					
						
							|  |  |  | 				var index_dir = this.config['index-dir'] || '.ImageGrid' | 
					
						
							| 
									
										
										
										
											2020-12-06 19:09:06 +03:00
										 |  |  | 				var path_tpl = that.config['preview-path-template'] | 
					
						
							| 
									
										
										
										
											2020-12-17 20:14:39 +03:00
										 |  |  | 					.replace(/\$INDEX|\$\{INDEX\}/g, index_dir) | 
					
						
							|  |  |  | 				var set_hidden_attrib = true | 
					
						
							| 
									
										
										
										
											2020-12-06 19:09:06 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				var img = this.images[gid] | 
					
						
							|  |  |  | 				var base = base_path  | 
					
						
							|  |  |  | 					|| img.base_path  | 
					
						
							|  |  |  | 					|| this.location.path | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-08 20:07:49 +03:00
										 |  |  | 				return Promise.all( | 
					
						
							|  |  |  | 					sizes | 
					
						
							|  |  |  | 						.map(function(size, i){ | 
					
						
							|  |  |  | 							var name = path = path_tpl | 
					
						
							|  |  |  | 								.replace(/\$RESOLUTION|\$\{RESOLUTION\}/g, parseInt(size)) | 
					
						
							|  |  |  | 								.replace(/\$GID|\$\{GID\}/g, gid)  | 
					
						
							|  |  |  | 								.replace(/\$NAME|\$\{NAME\}/g, img.name) | 
					
						
							| 
									
										
										
										
											2020-12-17 20:14:39 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 							// set the hidden flag on index dir...
 | 
					
						
							|  |  |  | 							// NOTE: this is done once per image...
 | 
					
						
							|  |  |  | 							// NOTE: we can't do this once per call as images can
 | 
					
						
							|  |  |  | 							// 		have different .base_path's...
 | 
					
						
							|  |  |  | 							set_hidden_attrib  | 
					
						
							|  |  |  | 								&& (process.platform == 'win32'  | 
					
						
							|  |  |  | 									|| process.platform == 'win64') | 
					
						
							|  |  |  | 								&& name.includes(index_dir) | 
					
						
							|  |  |  | 								&& cp.spawn('attrib', ['+h',  | 
					
						
							|  |  |  | 									pathlib.resolve( | 
					
						
							|  |  |  | 										base, | 
					
						
							|  |  |  | 										name.split(index_dir)[0],  | 
					
						
							|  |  |  | 										index_dir)])  | 
					
						
							|  |  |  | 							set_hidden_attrib = false | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-08 20:07:49 +03:00
										 |  |  | 							// NOTE: we are 'sync' here for several reasons, mainly because
 | 
					
						
							|  |  |  | 							// 		this is a small list and in this way we can take 
 | 
					
						
							|  |  |  | 							// 		advantage of OS file caching, and removing the queue
 | 
					
						
							|  |  |  | 							// 		overhead, though small makes this noticeably faster...
 | 
					
						
							|  |  |  | 							return that.makeResizedImage('sync', gid, size, base, {  | 
					
						
							|  |  |  | 									name,  | 
					
						
							|  |  |  | 									skipSmaller: true, | 
					
						
							|  |  |  | 									transform: false, | 
					
						
							| 
									
										
										
										
											2020-12-17 20:14:39 +03:00
										 |  |  | 									overwrite: false, | 
					
						
							| 
									
										
										
										
											2020-12-08 20:07:49 +03:00
										 |  |  | 									logger: logger_mode == 'gids' ?  | 
					
						
							|  |  |  | 										false  | 
					
						
							|  |  |  | 										: logger, | 
					
						
							|  |  |  | 								}) | 
					
						
							|  |  |  | 								// XXX handle errors -- rejected because image exists...
 | 
					
						
							| 
									
										
										
										
											2020-12-09 06:27:11 +03:00
										 |  |  | 								.then( | 
					
						
							|  |  |  | 									function(res){ | 
					
						
							|  |  |  | 										// update metadata...
 | 
					
						
							|  |  |  | 										if(!base_path){ | 
					
						
							|  |  |  | 											var preview = img.preview = img.preview || {}  | 
					
						
							|  |  |  | 											preview[parseInt(size) + 'px'] = name | 
					
						
							|  |  |  | 											that.markChanged | 
					
						
							|  |  |  | 												&& that.markChanged('images', [gid]) } | 
					
						
							|  |  |  | 										return [gid, size, name] }, | 
					
						
							|  |  |  | 									function(err){ | 
					
						
							| 
									
										
										
										
											2020-12-17 20:14:39 +03:00
										 |  |  | 										// XXX erro
 | 
					
						
							|  |  |  | 										logger  | 
					
						
							|  |  |  | 											&& logger.emit('skipped', `${gid} / ${size}`) | 
					
						
							| 
									
										
										
										
											2020-12-09 06:27:11 +03:00
										 |  |  | 									}) })) })], | 
					
						
							| 
									
										
										
										
											2020-12-17 23:19:42 +03:00
										 |  |  | 	// XXX EXPERIMENTAL: need a way to update the index when preview is 
 | 
					
						
							|  |  |  | 	// 		created (if we did not navigate away)
 | 
					
						
							|  |  |  | 	// 			- we could abort the update if we go away...
 | 
					
						
							|  |  |  | 	// 			- we could clone the index and if index.gid does not 
 | 
					
						
							|  |  |  | 	// 				match the main index use the clone to save....
 | 
					
						
							| 
									
										
										
										
											2020-12-19 14:59:34 +03:00
										 |  |  | 	// 		...the cloning approach would be quite simple:
 | 
					
						
							|  |  |  | 	// 			ig.clone().makePreviews()
 | 
					
						
							|  |  |  | 	// 		or:
 | 
					
						
							|  |  |  | 	// 			ig.peer.clone().makePreviews() // hypothetical api...
 | 
					
						
							|  |  |  | 	// 		the only question here is how to manage this...
 | 
					
						
							| 
									
										
										
										
											2020-12-17 23:19:42 +03:00
										 |  |  | 	// XXX change base_path to target path...
 | 
					
						
							|  |  |  | 	_makePreviews: ['- Sharp|File/Make image $previews (experimental)', | 
					
						
							|  |  |  | 		core.queueHandler('Make image previews',  | 
					
						
							|  |  |  | 			core.sessionQueueHandler('Getting image data for previews',  | 
					
						
							|  |  |  | 				// prepare the static data...
 | 
					
						
							|  |  |  | 				function(queue, _, images, sizes){ | 
					
						
							|  |  |  | 					// sync mode...
 | 
					
						
							|  |  |  | 					var args = [...arguments].slice(2) | 
					
						
							|  |  |  | 					if(queue == 'sync'){ | 
					
						
							|  |  |  | 						args.unshift(_) | 
					
						
							|  |  |  | 						var [images, sizes, ...args] = args } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					// get/normalize sizes....
 | 
					
						
							|  |  |  | 					var cfg_sizes = this.config['preview-sizes'].slice() || [] | 
					
						
							|  |  |  | 					cfg_sizes | 
					
						
							|  |  |  | 						.sort() | 
					
						
							|  |  |  | 						.reverse() | 
					
						
							|  |  |  | 					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 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					// XXX we should cache this on a previous stage...
 | 
					
						
							|  |  |  | 					var index_dir = this.config['index-dir'] || '.ImageGrid' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					// get/normalize images...
 | 
					
						
							|  |  |  | 					return [ | 
					
						
							|  |  |  | 						(images == null || images == 'all') ?  | 
					
						
							|  |  |  | 								this.data.getImages('all') | 
					
						
							|  |  |  | 							: images == 'current' ?  | 
					
						
							|  |  |  | 								[this.current] | 
					
						
							|  |  |  | 							: images instanceof Array ?  | 
					
						
							|  |  |  | 								images  | 
					
						
							|  |  |  | 							: [images], | 
					
						
							|  |  |  | 						sizes, | 
					
						
							|  |  |  | 						// name template -- partially filled...
 | 
					
						
							|  |  |  | 						this.config['preview-path-template'] | 
					
						
							|  |  |  | 							.replace(/\$INDEX|\$\{INDEX\}/g, index_dir), | 
					
						
							|  |  |  | 						// NOTE: this is not the most elegant way to go but
 | 
					
						
							|  |  |  | 						// 		it's better than getting it once per image...
 | 
					
						
							|  |  |  | 						index_dir, | 
					
						
							|  |  |  | 						...args, | 
					
						
							|  |  |  | 					] }, | 
					
						
							|  |  |  | 				// generate image paths...
 | 
					
						
							|  |  |  | 				function(gid, sizes, path_tpl, index_dir, base_path){ | 
					
						
							|  |  |  | 					var that = this | 
					
						
							|  |  |  | 					var img = this.images[gid] | 
					
						
							|  |  |  | 					var base = base_path  | 
					
						
							|  |  |  | 						|| img.base_path  | 
					
						
							|  |  |  | 						|| this.location.path | 
					
						
							|  |  |  | 					return [ | 
					
						
							|  |  |  | 						gid, | 
					
						
							|  |  |  | 						// source...
 | 
					
						
							|  |  |  | 						this.getImagePath(gid),  | 
					
						
							|  |  |  | 						// targets -- [[size, to], ...]...
 | 
					
						
							|  |  |  | 						sizes | 
					
						
							|  |  |  | 							.map(function(size){ | 
					
						
							|  |  |  | 								var name = path_tpl | 
					
						
							|  |  |  | 									.replace(/\$RESOLUTION|\$\{RESOLUTION\}/g, parseInt(size)) | 
					
						
							|  |  |  | 									.replace(/\$GID|\$\{GID\}/g, gid)  | 
					
						
							|  |  |  | 									.replace(/\$NAME|\$\{NAME\}/g, img.name) | 
					
						
							|  |  |  | 								return [ | 
					
						
							|  |  |  | 									size, | 
					
						
							|  |  |  | 									pathlib.resolve( | 
					
						
							|  |  |  | 										that.location.path, | 
					
						
							|  |  |  | 										pathlib.join(base, name)), | 
					
						
							|  |  |  | 								] }), | 
					
						
							|  |  |  | 						index_dir, | 
					
						
							|  |  |  | 					]}), | 
					
						
							|  |  |  | 			// generate the previews...
 | 
					
						
							|  |  |  | 			// NOTE: this is competely isolated...
 | 
					
						
							|  |  |  | 			// XXX args/logger is wrong here...
 | 
					
						
							|  |  |  | 			function([gid, source, targets, index_dir], logger){ | 
					
						
							|  |  |  | 				var that = this | 
					
						
							|  |  |  | 				//var logger_mode = this.config['preview-progress-mode'] || 'gids'
 | 
					
						
							|  |  |  | 				 | 
					
						
							|  |  |  | 				// NOTE: if this is false attrib will not be called...
 | 
					
						
							|  |  |  | 				var set_hidden_attrib = true | 
					
						
							|  |  |  | 				return Promise.all( | 
					
						
							|  |  |  | 					targets | 
					
						
							|  |  |  | 						.map(function([size, target]){ | 
					
						
							|  |  |  | 							// set the hidden flag on index dir...
 | 
					
						
							|  |  |  | 							// NOTE: this is done once per image...
 | 
					
						
							|  |  |  | 							// NOTE: we can't do this once per call as images can
 | 
					
						
							|  |  |  | 							// 		have different .base_path's...
 | 
					
						
							|  |  |  | 							set_hidden_attrib  | 
					
						
							|  |  |  | 								&& (process.platform == 'win32'  | 
					
						
							|  |  |  | 									|| process.platform == 'win64') | 
					
						
							|  |  |  | 								&& target.includes(index_dir) | 
					
						
							|  |  |  | 								&& cp.spawn('attrib', ['+h',  | 
					
						
							|  |  |  | 									pathlib.join(target.split(index_dir)[0], index_dir)])  | 
					
						
							|  |  |  | 							set_hidden_attrib = false | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 							// NOTE: we are 'sync' here for several reasons, mainly because
 | 
					
						
							|  |  |  | 							// 		this is a small list and in this way we can take 
 | 
					
						
							|  |  |  | 							// 		advantage of OS file caching, and removing the queue
 | 
					
						
							|  |  |  | 							// 		overhead, though small makes this noticeably faster...
 | 
					
						
							|  |  |  | 							return that.makeResizedImage('sync', [[source, target]], size, null, {  | 
					
						
							|  |  |  | 									name,  | 
					
						
							|  |  |  | 									skipSmaller: true, | 
					
						
							|  |  |  | 									transform: false, | 
					
						
							|  |  |  | 									overwrite: false, | 
					
						
							|  |  |  | 									//logger: logger_mode == 'gids' ? 
 | 
					
						
							|  |  |  | 									//	false 
 | 
					
						
							|  |  |  | 									//	: logger,
 | 
					
						
							|  |  |  | 								}) | 
					
						
							|  |  |  | 								.then( | 
					
						
							|  |  |  | 									function(res){ | 
					
						
							|  |  |  | 										// update metadata...
 | 
					
						
							|  |  |  | 										// XXX do this only if we are in the same index......
 | 
					
						
							|  |  |  | 										// 		...might be fun to create a session 
 | 
					
						
							|  |  |  | 										// 		queue for this at the start and if it 
 | 
					
						
							|  |  |  | 										// 		survives till this point we use it...
 | 
					
						
							|  |  |  | 										/* | 
					
						
							|  |  |  | 										if(!base_path){ | 
					
						
							|  |  |  | 											var preview = img.preview = img.preview || {}  | 
					
						
							|  |  |  | 											preview[parseInt(size) + 'px'] = name | 
					
						
							|  |  |  | 											that.markChanged | 
					
						
							|  |  |  | 												&& that.markChanged('images', [gid]) } | 
					
						
							|  |  |  | 										//*/
 | 
					
						
							|  |  |  | 										return [gid, size, name] }, | 
					
						
							|  |  |  | 									function(err){ | 
					
						
							|  |  |  | 										logger  | 
					
						
							|  |  |  | 											&& logger.emit('skipped', `${gid} / ${size}`) | 
					
						
							|  |  |  | 									}) })) })], | 
					
						
							| 
									
										
										
										
											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-12-02 18:49:45 +03:00
										 |  |  | 	// XXX revise logging and logger passing...
 | 
					
						
							| 
									
										
										
										
											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, .. ]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-06 02:25:55 +03:00
										 |  |  | 		This will: | 
					
						
							|  |  |  | 			- quickly reads/caches essential (.orientation and .flipped) metadata | 
					
						
							|  |  |  | 			- quickly read some non-essential but already there values | 
					
						
							|  |  |  | 			- generate priority previews for very large images (only when in index) | 
					
						
							| 
									
										
										
										
											2020-11-05 22:46:27 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		This will overwrite/update if: | 
					
						
							|  |  |  | 			- .orientation and .flipped iff image .orientation AND .flipped  | 
					
						
							|  |  |  | 				are unset or force is true | 
					
						
							|  |  |  | 			- metadata if image .metadata is not set or  | 
					
						
							|  |  |  | 				.metadata.ImageGridMetadata is not set | 
					
						
							|  |  |  | 			- all metadata if force is set to true | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-05 06:31:13 +03:00
										 |  |  | 		NOTE: this will effectively update metadata format to the new spec... | 
					
						
							| 
									
										
										
										
											2020-11-05 22:46:27 +03:00
										 |  |  | 		NOTE: for info on full metadata format see: .readMetadata(..) | 
					
						
							| 
									
										
										
										
											2020-11-02 05:33:29 +03:00
										 |  |  | 		`,
 | 
					
						
							| 
									
										
										
										
											2020-12-03 20:51:54 +03:00
										 |  |  | 		core.sessionQueueHandler('Cache image metadata',  | 
					
						
							| 
									
										
										
										
											2020-12-03 04:03:20 +03:00
										 |  |  | 			// XXX timeouts still need tweaking...
 | 
					
						
							|  |  |  | 			{quiet: true, pool_size: 2, busy_timeout: 400},  | 
					
						
							| 
									
										
										
										
											2020-12-03 05:19:50 +03:00
										 |  |  | 			//{quiet: true, pool_size: 2, busy_timeout_scale: 10}, 
 | 
					
						
							| 
									
										
										
										
											2020-12-02 18:49:45 +03:00
										 |  |  | 			// parse args...
 | 
					
						
							| 
									
										
										
										
											2020-12-03 20:51:54 +03:00
										 |  |  | 			function(queue, image, ...args){ | 
					
						
							| 
									
										
										
										
											2020-12-21 03:41:11 +03:00
										 |  |  | 				var that = this | 
					
						
							| 
									
										
										
										
											2020-12-21 05:29:17 +03:00
										 |  |  | 				var force = args[0] == 'force' | 
					
						
							| 
									
										
										
										
											2020-12-21 03:41:11 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				// expand images...
 | 
					
						
							|  |  |  | 				var images = image == 'all' ? | 
					
						
							|  |  |  | 						this.images.keys() | 
					
						
							|  |  |  | 					: image == 'loaded' ? | 
					
						
							|  |  |  | 						this.data.getImages('loaded') | 
					
						
							|  |  |  | 					: image instanceof Array ? | 
					
						
							|  |  |  | 						image | 
					
						
							|  |  |  | 					: [this.data.getImage(image || 'current')] | 
					
						
							|  |  |  | 				// narrow down the list...
 | 
					
						
							|  |  |  | 				images = force ?  | 
					
						
							|  |  |  | 					images  | 
					
						
							|  |  |  | 					: images | 
					
						
							|  |  |  | 						.filter(function(gid){ | 
					
						
							|  |  |  | 							var img = that.images[gid] | 
					
						
							|  |  |  | 							return img | 
					
						
							|  |  |  | 								// high priority must be preset...
 | 
					
						
							|  |  |  | 								&& ((img.orientation == null | 
					
						
							|  |  |  | 										&& img.flipped == null) | 
					
						
							|  |  |  | 									// update metadata...
 | 
					
						
							|  |  |  | 									|| (img.metadata || {}).ImageGridMetadata == null) }) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-02 18:49:45 +03:00
										 |  |  | 				return [ | 
					
						
							| 
									
										
										
										
											2020-12-21 03:41:11 +03:00
										 |  |  | 					images, | 
					
						
							| 
									
										
										
										
											2020-12-03 20:51:54 +03:00
										 |  |  | 					...args, | 
					
						
							| 
									
										
										
										
											2020-12-02 18:49:45 +03:00
										 |  |  | 				] }, | 
					
						
							| 
									
										
										
										
											2020-12-21 03:41:11 +03:00
										 |  |  | 			function(image, force, logger){ | 
					
						
							| 
									
										
										
										
											2020-12-02 18:49:45 +03:00
										 |  |  | 				var that = this | 
					
						
							| 
									
										
										
										
											2020-11-02 06:06:42 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-02 18:49:45 +03:00
										 |  |  | 				// XXX cache the image data???
 | 
					
						
							|  |  |  | 				var gid = this.data.getImage(image) | 
					
						
							|  |  |  | 				var img = this.images[gid] | 
					
						
							|  |  |  | 				var path = img && that.getImagePath(gid) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// XXX
 | 
					
						
							|  |  |  | 				//var base_path = that.location.load == 'loadIndex' ?
 | 
					
						
							|  |  |  | 				//	null
 | 
					
						
							|  |  |  | 				//	: tmp
 | 
					
						
							|  |  |  | 				//var base_path = img && img.base_path
 | 
					
						
							|  |  |  | 				var base_path | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 				// skip...
 | 
					
						
							|  |  |  | 				if(!(img && path | 
					
						
							|  |  |  | 						&& (force | 
					
						
							|  |  |  | 							// high priority must be preset...
 | 
					
						
							|  |  |  | 							|| (img.orientation == null | 
					
						
							|  |  |  | 								&& img.flipped == null) | 
					
						
							|  |  |  | 							// update metadata...
 | 
					
						
							|  |  |  | 							|| (img.metadata || {}).ImageGridMetadata == null))){ | 
					
						
							|  |  |  | 					return } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// XXX handle/report errors...
 | 
					
						
							|  |  |  | 				return sharp(that.getImagePath(gid)) | 
					
						
							|  |  |  | 					.metadata() | 
					
						
							|  |  |  | 					.then(function(metadata){ | 
					
						
							|  |  |  | 						// no metadata...
 | 
					
						
							|  |  |  | 						if(metadata == null){ | 
					
						
							|  |  |  | 							return } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						var o = normalizeOrientation(metadata.orientation) | 
					
						
							|  |  |  | 						;(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-05 22:46:27 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-02 18:49:45 +03:00
										 |  |  | 						// read the metadata...
 | 
					
						
							|  |  |  | 						var exif = metadata.exif  | 
					
						
							|  |  |  | 							&& exifReader(metadata.exif)  | 
					
						
							|  |  |  | 						exif | 
					
						
							|  |  |  | 							&& Object.assign( | 
					
						
							|  |  |  | 								img.metadata,  | 
					
						
							|  |  |  | 								exifReader2exiftool(exif, metadata.xmp)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						// if image too large, generate preview(s)...
 | 
					
						
							|  |  |  | 						// XXX EXPERIMENTAL...
 | 
					
						
							|  |  |  | 						var size_threshold = that.config['preview-generate-threshold'] | 
					
						
							|  |  |  | 						if(size_threshold | 
					
						
							|  |  |  | 								&& img.preview == null | 
					
						
							|  |  |  | 								&& Math.max(metadata.width, metadata.height) > size_threshold){ | 
					
						
							|  |  |  | 							logger && logger.emit('Image too large', gid) | 
					
						
							|  |  |  | 							// 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) } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						that.markChanged | 
					
						
							|  |  |  | 							&& that.markChanged('images', [gid]) | 
					
						
							|  |  |  | 						that.ribbons | 
					
						
							|  |  |  | 							&& that.ribbons.updateImage(gid)  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						return gid }) })], | 
					
						
							|  |  |  | 	cacheAllMetadata: ['- Sharp/Image/', | 
					
						
							| 
									
										
										
										
											2020-11-05 06:31:13 +03:00
										 |  |  | 		'cacheMetadata: "all" ...'], | 
					
						
							| 
									
										
										
										
											2020-12-20 06:12:47 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// XXX EXPERIMENTAL...
 | 
					
						
							| 
									
										
										
										
											2021-01-24 20:51:33 +03:00
										 |  |  | 	// 	XXX if we are not careful this may result in some data loss due 
 | 
					
						
							|  |  |  | 	// 		to unlinking or double edits before save... 
 | 
					
						
							|  |  |  | 	// 		(REVISE!!!)
 | 
					
						
							|  |  |  | 	// 	XXX it is also possible to save the foreground state while the 
 | 
					
						
							|  |  |  | 	// 		task is running... 
 | 
					
						
							|  |  |  | 	// 		this should not be destructive unless saving with the exact 
 | 
					
						
							|  |  |  | 	// 		same timestamp...
 | 
					
						
							|  |  |  | 	// 		...this however, if some structure is unlinked, can lead to 
 | 
					
						
							|  |  |  | 	// 		the later background save shadowing some earlier changes in 
 | 
					
						
							|  |  |  | 	// 		the foreground...
 | 
					
						
							|  |  |  | 	// XXX the number of places this can go wrong (see above) warrants a 
 | 
					
						
							|  |  |  | 	// 		rethink...
 | 
					
						
							|  |  |  | 	// 		...can we make .link() work like link-on-demand, i.e. actually 
 | 
					
						
							|  |  |  | 	// 		create the link on .clear() but before that use this???
 | 
					
						
							|  |  |  | 	// XXX move this to filesystem???
 | 
					
						
							|  |  |  | 	makeIndex: ['- File/', | 
					
						
							|  |  |  | 		core.doc`
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			.makeIndex() | 
					
						
							|  |  |  | 			.makeIndex(options) | 
					
						
							|  |  |  | 				-> promise | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		options format: | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				// default: true
 | 
					
						
							|  |  |  | 				linked: <bool>, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// default: true
 | 
					
						
							|  |  |  | 				metadata: <book> | 'full', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// default: true
 | 
					
						
							|  |  |  | 				previews: <book>, | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		NOTE: this will save the index in the background, this will not affect  | 
					
						
							|  |  |  | 			foreground .changes but will update the foreground data... | 
					
						
							|  |  |  | 			this will allow modifying stuff while the tasks are running and then  | 
					
						
							|  |  |  | 			saving the changes correctly and allow the user to leave the index... | 
					
						
							|  |  |  | 		`,
 | 
					
						
							|  |  |  | 		function(options={}){ | 
					
						
							|  |  |  | 			var that = options.linked === false ?  | 
					
						
							|  |  |  | 				this  | 
					
						
							|  |  |  | 				: this.link() | 
					
						
							|  |  |  | 			return Promise.all([ | 
					
						
							|  |  |  | 				// metadata...
 | 
					
						
							|  |  |  | 				options.metadata !== false | 
					
						
							|  |  |  | 					&& ((options.metadata == 'full'  | 
					
						
							|  |  |  | 							&& that.readAllMetadata) ? | 
					
						
							|  |  |  | 						// full (slow)...
 | 
					
						
							| 
									
										
										
										
											2021-01-24 20:53:58 +03:00
										 |  |  | 						that.readAllMetadata() | 
					
						
							| 
									
										
										
										
											2021-01-24 20:51:33 +03:00
										 |  |  | 						// partial (fast)...
 | 
					
						
							|  |  |  | 						: (that.cacheAllMetadata | 
					
						
							| 
									
										
										
										
											2021-01-24 20:56:07 +03:00
										 |  |  | 							&& that.cacheAllMetadata())), | 
					
						
							| 
									
										
										
										
											2021-01-24 20:51:33 +03:00
										 |  |  | 				// previews...
 | 
					
						
							|  |  |  | 				options.previews !== false | 
					
						
							|  |  |  | 					&& that.makePreviews | 
					
						
							|  |  |  | 					&& that.makePreviews(), | 
					
						
							|  |  |  | 			// save...
 | 
					
						
							|  |  |  | 			]).then(function(){ | 
					
						
							|  |  |  | 				that.saveIndex() }) }], | 
					
						
							| 
									
										
										
										
											2016-05-22 21:10:37 +03:00
										 |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-26 05:36:28 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											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-12-21 03:41:11 +03:00
										 |  |  | 		// NOTE: this is about as fast as filtering the images and 
 | 
					
						
							|  |  |  | 		// 		calling only on the ones needing caching...
 | 
					
						
							|  |  |  | 		// 		...but this is not a no-op, especially on very large 
 | 
					
						
							|  |  |  | 		// 		indexes...
 | 
					
						
							|  |  |  | 		// XXX this needs to be run in the background...
 | 
					
						
							| 
									
										
										
										
											2020-12-03 20:51:54 +03:00
										 |  |  | 		// XXX this is best done in a thread 
 | 
					
						
							| 
									
										
										
										
											2020-12-21 05:29:17 +03:00
										 |  |  | 		[['loadIndex', | 
					
						
							| 
									
										
										
										
											2020-12-21 03:41:11 +03:00
										 |  |  | 				'loadImages',  | 
					
						
							| 
									
										
										
										
											2020-11-05 22:46:27 +03:00
										 |  |  | 				'loadNewImages'], | 
					
						
							| 
									
										
										
										
											2020-11-27 02:33:46 +03:00
										 |  |  | 			'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...
 | 
					
						
							| 
									
										
										
										
											2016-06-03 04:46:51 +03:00
										 |  |  | 		['updateImage', | 
					
						
							|  |  |  | 			function(_, gid){ | 
					
						
							| 
									
										
										
										
											2020-11-05 06:31:13 +03:00
										 |  |  | 				var that = this | 
					
						
							| 
									
										
										
										
											2020-11-10 18:00:14 +03:00
										 |  |  | 				// NOTE: as this directly affects the visible lag, this 
 | 
					
						
							|  |  |  | 				// 		must be as fast as possible...
 | 
					
						
							| 
									
										
										
										
											2020-11-27 02:33:46 +03:00
										 |  |  | 				// NOTE: running .cacheMetadata(..) in sync mode here forces
 | 
					
						
							| 
									
										
										
										
											2020-12-03 20:51:54 +03:00
										 |  |  | 				// 		the image to update before it gets a change to get
 | 
					
						
							| 
									
										
										
										
											2020-11-27 02:33:46 +03:00
										 |  |  | 				// 		drawn...
 | 
					
						
							| 
									
										
										
										
											2020-11-10 18:00:14 +03:00
										 |  |  | 				;((this.images[gid] || {}).metadata || {}).ImageGridMetadata | 
					
						
							| 
									
										
										
										
											2020-12-03 20:51:54 +03:00
										 |  |  | 					|| this.cacheMetadata('sync', gid, false) }], | 
					
						
							| 
									
										
										
										
											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...
 | 
					
						
							| 
									
										
										
										
											2020-12-21 03:41:11 +03:00
										 |  |  | 										that.makePreviews(gid) }) } }) } }] | 
					
						
							| 
									
										
										
										
											2016-05-23 03:42:53 +03:00
										 |  |  | 		//*/
 | 
					
						
							| 
									
										
										
										
											2016-05-22 21:10:37 +03:00
										 |  |  | 	], | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-30 05:21:23 +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 }) |