| 
									
										
										
										
											2016-05-22 21:10:37 +03:00
										 |  |  | /********************************************************************** | 
					
						
							|  |  |  | *  | 
					
						
							|  |  |  | * | 
					
						
							|  |  |  | * | 
					
						
							|  |  |  | **********************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | define(function(require){ var module = {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //var DEBUG = DEBUG != null ? DEBUG : true
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var actions = require('lib/actions') | 
					
						
							|  |  |  | var features = require('lib/features') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var core = require('features/core') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | try{ | 
					
						
							|  |  |  | 	var sharp = requirejs('sharp') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } catch(err){ | 
					
						
							|  |  |  | 	sharp = null | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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') | 
					
						
							|  |  |  | 	var file = requirejs('./file') | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*********************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | if(typeof(process) != 'undefined'){ | 
					
						
							|  |  |  | 	var ensureDir = file.denodeify(fse.ensureDir) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*********************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var SharpActions = actions.Actions({ | 
					
						
							|  |  |  | 	config: { | 
					
						
							|  |  |  | 		'preview-path': '$INDEX/$RESOLUTIONpx', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		'preview-normalized': true, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-23 03:42:53 +03:00
										 |  |  | 		// XXX this repeats filesystem.FileSystemWriterActions.config['export-preview-sizes']
 | 
					
						
							| 
									
										
										
										
											2016-05-22 21:10:37 +03:00
										 |  |  | 		'preview-sizes': [ | 
					
						
							| 
									
										
										
										
											2016-05-22 23:11:12 +03:00
										 |  |  | 			1920, | 
					
						
							|  |  |  | 			1280, | 
					
						
							| 
									
										
										
										
											2016-05-22 21:10:37 +03:00
										 |  |  | 			900, | 
					
						
							|  |  |  | 			350, | 
					
						
							|  |  |  | 			150, | 
					
						
							|  |  |  | 			75, | 
					
						
							|  |  |  | 		] | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-22 23:11:12 +03:00
										 |  |  | 	// XXX BUG (nw.js): this does not work until child_process.fork(..) is fixed...
 | 
					
						
							|  |  |  | 	startWorker: ['- Sharp/', | 
					
						
							|  |  |  | 		function(){ | 
					
						
							|  |  |  | 			if(this.previewConstructorWorker){ | 
					
						
							|  |  |  | 				return | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			this.previewConstructorWorker = cp.form('./worker/preview-constructor') | 
					
						
							|  |  |  | 		}], | 
					
						
							|  |  |  | 	stopWorker: ['- Sharp/', | 
					
						
							|  |  |  | 		function(){ | 
					
						
							|  |  |  | 			this.previewConstructorWorker && this.previewConstructorWorker.kill() | 
					
						
							|  |  |  | 			delete this.previewConstructorWorker | 
					
						
							|  |  |  | 		}], | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-22 21:10:37 +03:00
										 |  |  | 	//	.makePreviews()
 | 
					
						
							|  |  |  | 	//	.makePreviews('current')
 | 
					
						
							|  |  |  | 	//		-> actions
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	//	.makePreviews(gid)
 | 
					
						
							|  |  |  | 	//		-> actions
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	//	.makePreviews([gid, gid, ..])
 | 
					
						
							|  |  |  | 	//		-> actions
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	//	.makePreviews('all')
 | 
					
						
							|  |  |  | 	//		-> actions
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// XXX should this account for non-jpeg images???
 | 
					
						
							| 
									
										
										
										
											2016-05-22 23:11:12 +03:00
										 |  |  | 	// XXX do this in the background...
 | 
					
						
							| 
									
										
										
										
											2016-05-22 21:10:37 +03:00
										 |  |  | 	makePreviews: ['Sharp/Make image previews', | 
					
						
							|  |  |  | 		function(images, sizes, logger){ | 
					
						
							|  |  |  | 			logger = logger || this.logger | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			images = images || this.current | 
					
						
							|  |  |  | 			// keywords...
 | 
					
						
							|  |  |  | 			images = images == 'all' ? this.data.getImages('all') | 
					
						
							|  |  |  | 				: images == 'current' ? this.current | 
					
						
							|  |  |  | 				: images | 
					
						
							|  |  |  | 			images = images instanceof Array ? images : [images] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			var cfg_sizes = this.config['preview-sizes'] || [] | 
					
						
							|  |  |  | 			cfg_sizes | 
					
						
							|  |  |  | 				.sort() | 
					
						
							|  |  |  | 				.reverse() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-23 03:42:53 +03:00
										 |  |  | 			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 | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2016-05-22 21:10:37 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			var that = this | 
					
						
							|  |  |  | 			return Promise.all(images.map(function(gid){ | 
					
						
							|  |  |  | 				var data = that.images[gid] | 
					
						
							|  |  |  | 				var path = that.getImagePath(gid) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-23 03:42:53 +03:00
										 |  |  | 				var preview = data.preview = data.preview || {} | 
					
						
							| 
									
										
										
										
											2016-05-22 21:10:37 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-23 03:42:53 +03:00
										 |  |  | 				var img = sharp(path) | 
					
						
							| 
									
										
										
										
											2016-05-22 21:10:37 +03:00
										 |  |  | 				return img.metadata().then(function(metadata){ | 
					
						
							|  |  |  | 					var orig_res = Math.max(metadata.width, metadata.height) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					return Promise.all(sizes.map(function(res){ | 
					
						
							|  |  |  | 						// skip if image is smaller than res...
 | 
					
						
							|  |  |  | 						if(res >= orig_res){ | 
					
						
							|  |  |  | 							return  | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						var ext = data.ext || '' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						// build the target path...
 | 
					
						
							|  |  |  | 						var target = (that.config['preview-path'] || '$INDEX') | 
					
						
							|  |  |  | 							.replace(/\$INDEX|\$\{INDEX\}/g, that.config['index-dir']) | 
					
						
							|  |  |  | 							.replace(/\$RESOLUTION|\$\{RESOLUTION\}/g, res) | 
					
						
							|  |  |  | 						// XXX do we need to account for non-jpeg extensions???
 | 
					
						
							|  |  |  | 						var target = pathlib.join(target, gid +' - '+ data.name + ext) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						var base = data.base_path || that.location.path | 
					
						
							|  |  |  | 						var path = pathlib.join(base, target) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						logger && logger.emit('queued', target) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						return ensureDir(pathlib.dirname(path)) | 
					
						
							|  |  |  | 							.then(function(){ | 
					
						
							|  |  |  | 								// check if image exists...
 | 
					
						
							|  |  |  | 								if(fse.existsSync(path)){ | 
					
						
							|  |  |  | 									preview[res + 'px'] = target | 
					
						
							|  |  |  | 									that.markChanged(gid) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 									logger && logger.emit('skipped', target) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 									return | 
					
						
							|  |  |  | 								} | 
					
						
							|  |  |  | 							 | 
					
						
							|  |  |  | 								return img.clone() | 
					
						
							|  |  |  | 									.resize(res, res) | 
					
						
							|  |  |  | 									.max() | 
					
						
							|  |  |  | 									.interpolateWith('nohalo') | 
					
						
							|  |  |  | 									.withMetadata() | 
					
						
							|  |  |  | 									.toFile(path) | 
					
						
							|  |  |  | 										.then(function(){ | 
					
						
							|  |  |  | 											preview[res + 'px'] = target | 
					
						
							|  |  |  | 											that.markChanged(gid) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 											logger && logger.emit('done', target) | 
					
						
							|  |  |  | 										}) | 
					
						
							|  |  |  | 							}) | 
					
						
							|  |  |  | 					})) | 
					
						
							|  |  |  | 				}) | 
					
						
							|  |  |  | 			})) | 
					
						
							|  |  |  | 		}], | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var Sharp =  | 
					
						
							|  |  |  | module.Sharp = core.ImageGridFeatures.Feature({ | 
					
						
							|  |  |  | 	title: '', | 
					
						
							|  |  |  | 	doc: '', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	tag: 'sharp', | 
					
						
							|  |  |  | 	depends: [ | 
					
						
							|  |  |  | 		'location', | 
					
						
							|  |  |  | 	], | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	actions: SharpActions,  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	isApplicable: function(){ return !!sharp }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	handlers: [ | 
					
						
							| 
									
										
										
										
											2016-05-22 23:11:12 +03:00
										 |  |  | 		// XXX need to:
 | 
					
						
							|  |  |  | 		// 		- if image too large to set the preview to "loading..."
 | 
					
						
							|  |  |  | 		// 		- create previews...
 | 
					
						
							|  |  |  | 		// 		- update image...
 | 
					
						
							| 
									
										
										
										
											2016-05-23 03:42:53 +03:00
										 |  |  | 		/* | 
					
						
							| 
									
										
										
										
											2016-05-22 21:10:37 +03:00
										 |  |  | 		['updateImage.pre', | 
					
						
							|  |  |  | 			function(gid){ | 
					
						
							|  |  |  | 				var that = this | 
					
						
							|  |  |  | 				if(this.images[gid].preview == null){ | 
					
						
							|  |  |  | 					sharp(this.getImagePath(gid)) | 
					
						
							|  |  |  | 						.metadata() | 
					
						
							|  |  |  | 						.then(function(metadata){ | 
					
						
							| 
									
										
										
										
											2016-05-22 23:11:12 +03:00
										 |  |  | 							// current image is larger than any of the previews...
 | 
					
						
							| 
									
										
										
										
											2016-05-22 21:10:37 +03:00
										 |  |  | 							if(Math.max(metadata.width, metadata.height)  | 
					
						
							|  |  |  | 									> Math.max.apply(Math, that.config['preview-sizes'])){ | 
					
						
							| 
									
										
										
										
											2016-05-22 23:11:12 +03:00
										 |  |  | 								// create the currently needed preview first...
 | 
					
						
							|  |  |  | 								that.makePreviews(gid, that.ribbons.getVisibleImageSize()) | 
					
						
							|  |  |  | 									.then(function(){ | 
					
						
							|  |  |  | 										// load the created preview...
 | 
					
						
							|  |  |  | 										that.ribbons.updateImage(gid) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 										// create the rest...
 | 
					
						
							|  |  |  | 										that.makePreviews(gid) | 
					
						
							|  |  |  | 									}) | 
					
						
							| 
									
										
										
										
											2016-05-22 21:10:37 +03:00
										 |  |  | 							} | 
					
						
							|  |  |  | 						}) | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			}] | 
					
						
							| 
									
										
										
										
											2016-05-23 03:42:53 +03:00
										 |  |  | 		//*/
 | 
					
						
							| 
									
										
										
										
											2016-05-22 21:10:37 +03:00
										 |  |  | 	], | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /********************************************************************** | 
					
						
							|  |  |  | * vim:set ts=4 sw=4 :                                                */ | 
					
						
							|  |  |  | return module }) |