mirror of
				https://github.com/flynx/ImageGrid.git
				synced 2025-10-30 02:40:08 +00:00 
			
		
		
		
	cleanup...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
		
							parent
							
								
									9c72528908
								
							
						
					
					
						commit
						c750895a4a
					
				| @ -185,440 +185,9 @@ var SharpActions = actions.Actions({ | |||||||
| 		// 		from filesystem.IndexFormat...
 | 		// 		from filesystem.IndexFormat...
 | ||||||
| 	}, | 	}, | ||||||
| 
 | 
 | ||||||
| 	// XXX either make this a session task or make this survive loading 
 |  | ||||||
| 	// 		a new index...
 |  | ||||||
| 	// XXX revise return values...
 | 	// XXX revise return values...
 | ||||||
| 	// XXX make backup name pattern configurable...
 | 	// XXX make backup name pattern configurable...
 | ||||||
| 	// XXX CROP ready for crop support...
 | 	// XXX CROP ready for crop support...
 | ||||||
| 	_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. |  | ||||||
| 		`,
 |  | ||||||
| 		core.sessionQueueHandler('Make resized image',  |  | ||||||
| 			// get/normalize images...
 |  | ||||||
| 			// XXX if this is to be a global task (i.e. .queueHandler(..)) we'll 
 |  | ||||||
| 			// 		need to get all the image data here...
 |  | ||||||
| 			// 		...paths and orientation data...
 |  | ||||||
| 			function(queue, images, size, path, options){ |  | ||||||
| 				// sanity check...
 |  | ||||||
| 				if(arguments.length < 4){ |  | ||||||
| 					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], |  | ||||||
| 					...[...arguments].slice(2), |  | ||||||
| 				]}, |  | ||||||
| 			function(gid, size, path, options={}){ |  | ||||||
| 				var that = this |  | ||||||
| 
 |  | ||||||
| 				// sizing...
 |  | ||||||
| 				var fit =  |  | ||||||
| 					typeof(size) == typeof('str') ? |  | ||||||
| 						(size.endsWith('px') ? |  | ||||||
| 							'inside' |  | ||||||
| 						: size.endsWith('p') ? |  | ||||||
| 							'outside' |  | ||||||
| 						: 'inside') |  | ||||||
| 					: 'inside' |  | ||||||
| 				size = parseInt(size) |  | ||||||
| 				// options...
 |  | ||||||
| 				var { |  | ||||||
| 					// naming...
 |  | ||||||
| 					name,  |  | ||||||
| 					data,  |  | ||||||
| 
 |  | ||||||
| 					// file handling...
 |  | ||||||
| 					enlarge, |  | ||||||
| 					skipSmaller, |  | ||||||
| 					overwrite, |  | ||||||
| 
 |  | ||||||
| 					// transformations...
 |  | ||||||
| 					transform,  |  | ||||||
| 					// XXX CROP not implemented...
 |  | ||||||
| 					//crop, 
 |  | ||||||
| 
 |  | ||||||
| 					timestamp, |  | ||||||
| 					//logger, 
 |  | ||||||
| 				} = options |  | ||||||
| 				// defaults...
 |  | ||||||
| 				name = name || '%n' |  | ||||||
| 				transform = transform === undefined ?  |  | ||||||
| 					true  |  | ||||||
| 					: transform |  | ||||||
| 				timestamp = timestamp || Date.timeStamp() |  | ||||||
| 
 |  | ||||||
| 				// 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 || '') } |  | ||||||
| 
 |  | ||||||
| 				// skip non-images...
 |  | ||||||
| 				if(!['image', null, undefined] |  | ||||||
| 						.includes(this.images[gid].type)){ |  | ||||||
| 					// XXX what should we return???
 |  | ||||||
| 					return Promise.resolve() } |  | ||||||
| 
 |  | ||||||
| 				// paths...
 |  | ||||||
| 				var source = this.getImagePath(gid) |  | ||||||
| 				var to = 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)) |  | ||||||
| 
 |  | ||||||
| 				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(){ |  | ||||||
| 											var img = that.images[gid] |  | ||||||
| 											if(transform && (img.orientation || img.flipped)){ |  | ||||||
| 												img.orientation |  | ||||||
| 													&& this.rotate(img.orientation) |  | ||||||
| 												img.flipped |  | ||||||
| 													&& img.flipped.includes('horizontal') |  | ||||||
| 													&& this.flip() } |  | ||||||
| 												img.flipped |  | ||||||
| 													&& img.flipped.includes('vertical') |  | ||||||
| 													&& this.flop()  |  | ||||||
| 											// XXX CROP
 |  | ||||||
| 											//if(crop){
 |  | ||||||
| 											//	// XXX
 |  | ||||||
| 											//}
 |  | ||||||
| 										}) |  | ||||||
| 										.resize({ |  | ||||||
| 											width: size, |  | ||||||
| 											height: size, |  | ||||||
| 											fit: fit, |  | ||||||
| 											withoutEnlargement: !enlarge, |  | ||||||
| 										}) |  | ||||||
| 										.withMetadata() |  | ||||||
| 										.toFile(to)  |  | ||||||
| 										.then(function(){ |  | ||||||
| 											// XXX what should we return???
 |  | ||||||
| 											return to }) }) }) })], |  | ||||||
| 
 |  | ||||||
| 	_makeResizedImage2: ['- 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. |  | ||||||
| 		`,
 |  | ||||||
| 		core.queueHandler('Make resized image',  |  | ||||||
| 			// queue the image data...
 |  | ||||||
| 			// NOTE: after this runs we should be completely independent 
 |  | ||||||
| 			// 		of the current index...
 |  | ||||||
| 			// XXX for a very large number of images this can block for 
 |  | ||||||
| 			// 		a substantial amount of time...
 |  | ||||||
| 			function(queue, images, size, path, options){ |  | ||||||
| 				var that = this |  | ||||||
| 				// sanity check...
 |  | ||||||
| 				if(arguments.length < 4){ |  | ||||||
| 					throw new Error('.makeResizedImage(..): ' |  | ||||||
| 						+'need at least: images, size and path.') } |  | ||||||
| 				// options...
 |  | ||||||
| 				var { |  | ||||||
| 					name,  |  | ||||||
| 					data,  |  | ||||||
| 				} = options || {} |  | ||||||
| 				name = name || '%n' |  | ||||||
| 				// [source, to, image], ...args
 |  | ||||||
| 				return [ |  | ||||||
| 					((images == null || images == 'all') ?  |  | ||||||
| 								this.data.getimages('all') |  | ||||||
| 							: images == 'current' ?  |  | ||||||
| 								[this.current] |  | ||||||
| 							: images instanceof array ?  |  | ||||||
| 								images  |  | ||||||
| 							: [images]) |  | ||||||
| 						.map(function(gid){ |  | ||||||
| 							var image = that.images[gid] |  | ||||||
| 							// skip non-images...
 |  | ||||||
| 							if(!image || !['image', null, undefined] |  | ||||||
| 									.includes(image.type)){ |  | ||||||
| 								return [] } |  | ||||||
| 							return [[ |  | ||||||
| 								// source...
 |  | ||||||
| 								that.getimagepath(gid), |  | ||||||
| 								// target...
 |  | ||||||
| 								pathlib.resolve( |  | ||||||
| 									that.location.path, |  | ||||||
| 									pathlib.join( |  | ||||||
| 										path,  |  | ||||||
| 										// if name is not a pattern do not re-format it...
 |  | ||||||
| 										name.includes('%') ? |  | ||||||
| 											that.formatimagename(name, gid, data || {}) |  | ||||||
| 											: name)), |  | ||||||
| 								// image data...
 |  | ||||||
| 								// note: we include only the stuff we need...
 |  | ||||||
| 								{ |  | ||||||
| 									orientation: image.orientation, |  | ||||||
| 									flipped: image.flipped, |  | ||||||
| 									// crop...
 |  | ||||||
| 								}, |  | ||||||
| 							]] }) |  | ||||||
| 						.flat(), |  | ||||||
| 					...[...arguments].slice(2), |  | ||||||
| 				]}, |  | ||||||
| 			function([source, to, image], size, _, options={}){ |  | ||||||
| 				// 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, |  | ||||||
| 										}) |  | ||||||
| 										.withMetadata() |  | ||||||
| 										.toFile(to)  |  | ||||||
| 										.then(function(){ |  | ||||||
| 											// XXX what should we return???
 |  | ||||||
| 											return to }) }) }) })], |  | ||||||
| 
 |  | ||||||
| 	// XXX we need to split this into two stages:
 |  | ||||||
| 	// 			- session queue handler
 |  | ||||||
| 	// 			- global queue handler
 |  | ||||||
| 	// 		i.e. call the second queue generator when the first one completes...
 |  | ||||||
| 	// 		or in other works chain queues -- essentially this is like 
 |  | ||||||
| 	// 		calling .then(..) on a queue but doing it at definition...
 |  | ||||||
| 	makeResizedImage: ['- Image/', | 	makeResizedImage: ['- Image/', | ||||||
| 		core.doc`Make resized image(s)...
 | 		core.doc`Make resized image(s)...
 | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user