mirror of
				https://github.com/flynx/ImageGrid.git
				synced 2025-10-30 19:00:09 +00:00 
			
		
		
		
	added several new image sorting algorithms...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
		
							parent
							
								
									a5d64b031c
								
							
						
					
					
						commit
						0bdc98b3e1
					
				
							
								
								
									
										145
									
								
								ui/data.js
									
									
									
									
									
								
							
							
						
						
									
										145
									
								
								ui/data.js
									
									
									
									
									
								
							| @ -262,24 +262,23 @@ function cmp(a, b, get){ | |||||||
| // NOTE: this expects gids...
 | // NOTE: this expects gids...
 | ||||||
| function imageDateCmp(a, b, get, data){ | function imageDateCmp(a, b, get, data){ | ||||||
| 	data = data == null ? IMAGES : data | 	data = data == null ? IMAGES : data | ||||||
| 	if(get == null){ | 	if(get != null){ | ||||||
| 		return data[b].ctime - data[a].ctime | 		a = get(a) | ||||||
| 	} else { | 		b = get(b) | ||||||
| 		return data[get(b)].ctime - data[get(a)].ctime |  | ||||||
| 	} | 	} | ||||||
|  | 	return data[b].ctime - data[a].ctime | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| // NOTE: this expects gids...
 | // NOTE: this expects gids...
 | ||||||
| function imageNameCmp(a, b, get, data){ | function imageNameCmp(a, b, get, data){ | ||||||
| 	data = data == null ? IMAGES : data | 	data = data == null ? IMAGES : data | ||||||
| 	if(get == null){ | 	if(get != null){ | ||||||
| 		a = data[a].path.split('/').pop() | 		a = get(a) | ||||||
| 		b = data[b].path.split('/').pop() | 		b = get(b) | ||||||
| 	} else { |  | ||||||
| 		a = data[get(a)].path.split('/').pop() |  | ||||||
| 		b = data[get(b)].path.split('/').pop() |  | ||||||
| 	} | 	} | ||||||
|  | 	a = data[a].path.split('/').pop() | ||||||
|  | 	b = data[b].path.split('/').pop() | ||||||
| 	if(a == b){ | 	if(a == b){ | ||||||
| 		return 0 | 		return 0 | ||||||
| 	} else if(a < b){ | 	} else if(a < b){ | ||||||
| @ -290,14 +289,87 @@ function imageNameCmp(a, b, get, data){ | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | // Get the first sequence of numbers in the file name...
 | ||||||
|  | function getImageNameSeq(gid, data){ | ||||||
|  | 	data = data == null ? IMAGES : data | ||||||
|  | 	var n = data[gid].path.split('/').pop() | ||||||
|  | 	var r = /([0-9]+)/m.exec(n) | ||||||
|  | 	return r == null ? n : parseInt(r[1]) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Get the first sequence of numbers in the file name but only if it is
 | ||||||
|  | // at the filename start...
 | ||||||
|  | function getImageNameLeadingSeq(gid, data){ | ||||||
|  | 	data = data == null ? IMAGES : data | ||||||
|  | 	var n = data[gid].path.split('/').pop() | ||||||
|  | 	var r = /^([0-9]+)/g.exec(n) | ||||||
|  | 	return r == null ? n : parseInt(r[1]) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | // Compare images by sequence number (in filename) or by filename
 | ||||||
|  | //
 | ||||||
|  | // Examples:
 | ||||||
|  | // 	"1 file name", "012-file", "file 123 name", "DSC_1234"
 | ||||||
|  | //
 | ||||||
|  | // NOTE: if there are more than one sequence numbers in a filename then
 | ||||||
|  | // 		only the first is considered.
 | ||||||
|  | // NOTE: images with sequence number always precede images with plain 
 | ||||||
|  | // 		filenames...
 | ||||||
|  | function imageSeqOrNameCmp(a, b, get, data, get_seq){ | ||||||
|  | 	data = data == null ? IMAGES : data | ||||||
|  | 	get_seq = get_seq == null ? getImageNameSeq : get_seq | ||||||
|  | 	if(get != null){ | ||||||
|  | 		a = get(a) | ||||||
|  | 		b = get(b) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	var aa = get_seq(a, data) | ||||||
|  | 	var bb = get_seq(b, data) | ||||||
|  | 
 | ||||||
|  | 	// special case: seq, name
 | ||||||
|  | 	if(typeof(aa) == typeof(123) && typeof(bb) == typeof('str')){ return -1 } | ||||||
|  | 	// special case: name, seq
 | ||||||
|  | 	if(typeof(aa) == typeof('str') && typeof(bb) == typeof(123)){ return +1 } | ||||||
|  | 
 | ||||||
|  | 	// get the names if there are no sequence numbers...
 | ||||||
|  | 	// NOTE: at this point both a and b are either numbers or NaN's...
 | ||||||
|  | 	a = isNaN(aa) ? data[a].path.split('/').pop() : aa | ||||||
|  | 	b = isNaN(bb) ? data[b].path.split('/').pop() : bb | ||||||
|  | 
 | ||||||
|  | 	// do the actual comparison
 | ||||||
|  | 	if(a == b){ | ||||||
|  | 		return 0 | ||||||
|  | 	} else if(a < b){ | ||||||
|  | 		return -1 | ||||||
|  | 	} else { | ||||||
|  | 		return +1 | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Sort images XP-style
 | ||||||
|  | //
 | ||||||
|  | // This will consider sequence numbers if they are at the start of the 
 | ||||||
|  | // filename.
 | ||||||
|  | // 
 | ||||||
|  | // Examples:
 | ||||||
|  | // 	"1 file name", "012-file"
 | ||||||
|  | //
 | ||||||
|  | // NOTE: images with sequence number always precede images with plain 
 | ||||||
|  | // 		filenames...
 | ||||||
|  | function imageXPStyleFileNameCmp(a, b, get, data){ | ||||||
|  | 	return imageSeqOrNameCmp(a, b, get, data, getImageNameLeadingSeq) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| // NOTE: this expects gids...
 | // NOTE: this expects gids...
 | ||||||
| function imageOrderCmp(a, b, get, data){ | function imageOrderCmp(a, b, get, data){ | ||||||
| 	data = data == null ? DATA : data | 	data = data == null ? DATA : data | ||||||
| 	if(get == null){ | 	if(get != null){ | ||||||
| 		return data.order.indexOf(a) - data.order.indexOf(b) | 		a = get(a) | ||||||
| 	} else { | 		b = get(b) | ||||||
| 		return data.order.indexOf(get(a)) - data.order.indexOf(get(b)) |  | ||||||
| 	} | 	} | ||||||
|  | 	return data.order.indexOf(a) - data.order.indexOf(b) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @ -1785,6 +1857,12 @@ function sortImagesByDate(reverse){ | |||||||
| function sortImagesByFileName(reverse){ | function sortImagesByFileName(reverse){ | ||||||
| 	return sortImages(imageNameCmp, reverse) | 	return sortImages(imageNameCmp, reverse) | ||||||
| } | } | ||||||
|  | function sortImagesByFileSeqOrName(reverse){ | ||||||
|  | 	return sortImages(imageSeqOrNameCmp, reverse) | ||||||
|  | } | ||||||
|  | function sortImagesByFileNameXPStyle(reverse){ | ||||||
|  | 	return sortImages(imageXPStyleFileNameCmp, reverse) | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| // Sort images by name while taking into account sequence overflows
 | // Sort images by name while taking into account sequence overflows
 | ||||||
| @ -1793,7 +1871,9 @@ function sortImagesByFileName(reverse){ | |||||||
| // *9999 and then resets to *0001...
 | // *9999 and then resets to *0001...
 | ||||||
| //
 | //
 | ||||||
| // For this to be applicable:
 | // For this to be applicable:
 | ||||||
| // 	- filenames must comply with /....[0-9]{4}/
 | // 	- ALL filenames must contain a sequence number
 | ||||||
|  | // 		XXX do we need to make this more strict?
 | ||||||
|  | // 			...for example make name.split(<seq>) equal for all files
 | ||||||
| // 	- the total number of files in sequence is < 10K
 | // 	- the total number of files in sequence is < 10K
 | ||||||
| // 		XXX a simplification...
 | // 		XXX a simplification...
 | ||||||
| // 			there could be more than 10K images but then we will need to
 | // 			there could be more than 10K images but then we will need to
 | ||||||
| @ -1805,10 +1885,12 @@ function sortImagesByFileName(reverse){ | |||||||
| // 		number of files in set
 | // 		number of files in set
 | ||||||
| // 		XXX a simplification...
 | // 		XXX a simplification...
 | ||||||
| //
 | //
 | ||||||
|  | // NOTE: at this pint the gap size must be above proximity*10
 | ||||||
| // NOTE: if any of the above conditions is not applicable this will
 | // NOTE: if any of the above conditions is not applicable this will
 | ||||||
| // 		essentially revert to sortImagesByFileName(...)
 | // 		essentially revert to sortImagesByFileSeqOrName(...)
 | ||||||
| // NOTE: this will cut at the largest gap between sequence numbers.
 | // NOTE: this will cut at the largest gap between sequence numbers.
 | ||||||
| //
 | //
 | ||||||
|  | // XXX it would be a good idea to account for folder name sequencing...
 | ||||||
| // XXX it's also a good idea to write an image serial number sort...
 | // XXX it's also a good idea to write an image serial number sort...
 | ||||||
| // XXX is this overcomplicated???
 | // XXX is this overcomplicated???
 | ||||||
| //
 | //
 | ||||||
| @ -1816,54 +1898,50 @@ function sortImagesByFileName(reverse){ | |||||||
| // 		ever know it's here, if we replace it with the thee line dumb
 | // 		ever know it's here, if we replace it with the thee line dumb
 | ||||||
| // 		sortImagesByFileName(...) then things get "annoying" every 10K 
 | // 		sortImagesByFileName(...) then things get "annoying" every 10K 
 | ||||||
| // 		images :)
 | // 		images :)
 | ||||||
| function sortImagesByNameWithSeqOverflow(reverse, proximity){ | function sortImagesByFileNameSeqWithOverflow(reverse, proximity){ | ||||||
| 	proximity = proximity == null ? 10 : proximity | 	proximity = proximity == null ? 10 : proximity | ||||||
| 
 | 
 | ||||||
| 	// prepare to sort and check names...
 | 	// prepare to sort and check names...
 | ||||||
| 	// NOTE: we do not usually have a filename seq 0000...
 | 	// NOTE: we do not usually have a filename seq 0000...
 | ||||||
| 	if(DATA.order.length < 9999){ | 	if(DATA.order.length < 9999){ | ||||||
| 		var pattern = /....[0-9]{4}[a-z]?(\....[.])?/ |  | ||||||
| 		var need_to_fix = true | 		var need_to_fix = true | ||||||
| 
 | 
 | ||||||
| 		function cmp(a, b){ | 		function cmp(a, b){ | ||||||
| 			if(need_to_fix){ | 			if(need_to_fix){ | ||||||
| 				// check filename compliance...
 | 				if(typeof(getImageNameSeq(a)) == typeof('str')  | ||||||
| 				var aa = pattern.test(IMAGES[a].path.split('/').pop()) | 						|| typeof(getImageNameSeq(b)) == typeof('str')){ | ||||||
| 				var bb = pattern.test(IMAGES[b].path.split('/').pop()) |  | ||||||
| 				if(!aa && !bb){ |  | ||||||
| 					need_to_fix = false | 					need_to_fix = false | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 			return imageNameCmp(a, b) | 			return imageSeqOrNameCmp(a, b) | ||||||
| 		} |  | ||||||
| 		function getSeq(gid){ |  | ||||||
| 			return parseInt(IMAGES[gid].path.split('/').pop().slice(4)) |  | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 	// revert to normal sort my name...
 | 	// revert to normal sort my name...
 | ||||||
| 	// XXX this is not needed but will make things faster...
 |  | ||||||
| 	} else { | 	} else { | ||||||
|  | 		// XXX make this more cleaver -- split the set into 10K chunks and
 | ||||||
|  | 		// 		sort the chunks too...
 | ||||||
| 		return sortImagesByFileName(reverse) | 		return sortImagesByFileName(reverse) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	DATA.order.sort(cmp) | 	DATA.order.sort(cmp) | ||||||
| 
 | 
 | ||||||
|  | 	// find and fix the gap...
 | ||||||
| 	if(need_to_fix  | 	if(need_to_fix  | ||||||
| 			// check if first and last are close to 0001 and 9999 resp.
 | 			// check if first and last are close to 0001 and 9999 resp.
 | ||||||
| 			&& getSeq(DATA.order[0]) <= proximity | 			&& getImageNameSeq(DATA.order[0]) <= proximity | ||||||
| 			&& getSeq(DATA.order[DATA.order.length-1]) >= 9999-proximity){ | 			&& getImageNameSeq(DATA.order[DATA.order.length-1]) >= 9999-proximity){ | ||||||
| 		// find the largest gap position...
 | 		// find the largest gap position...
 | ||||||
| 		var pos = null | 		var pos = null | ||||||
| 		var gap = 0 | 		var gap = 0 | ||||||
| 		for(var i=1; i<DATA.order.length; i++){ | 		for(var i=1; i<DATA.order.length; i++){ | ||||||
| 			var n_gap = Math.max(getSeq(DATA.order[i])-getSeq(DATA.order[i-1]), gap) | 			var n_gap = Math.max(getImageNameSeq(DATA.order[i])-getImageNameSeq(DATA.order[i-1]), gap) | ||||||
| 			if(n_gap != gap){ | 			if(n_gap != gap){ | ||||||
| 				pos = i | 				pos = i | ||||||
| 				gap = n_gap | 				gap = n_gap | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		// split and rearrange the order chunks...
 | 		// split and rearrange the order chunks...
 | ||||||
| 		if(gap > proximity){ | 		if(gap > proximity*10){ | ||||||
| 			DATA.order = DATA.order.splice(pos).concat(DATA.order) | 			DATA.order = DATA.order.splice(pos).concat(DATA.order) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| @ -1875,11 +1953,6 @@ function sortImagesByNameWithSeqOverflow(reverse, proximity){ | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| // Set the default filename sort...
 |  | ||||||
| // XXX is this the correct way to do this???
 |  | ||||||
| var sortImagesByName = sortImagesByNameWithSeqOverflow |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 | 
 | ||||||
| /************************************************** Manual sorting ***/ | /************************************************** Manual sorting ***/ | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1173,6 +1173,9 @@ button:hover { | |||||||
| .overlay-block .dialog table tr td:last-child { | .overlay-block .dialog table tr td:last-child { | ||||||
|   color: silver; |   color: silver; | ||||||
| } | } | ||||||
|  | .overlay-block .dialog .choice .item { | ||||||
|  |   text-align: left; | ||||||
|  | } | ||||||
| /************************************************************ Help ***/ | /************************************************************ Help ***/ | ||||||
| /* XXX make this more generic, and not just for the keyboard... */ | /* XXX make this more generic, and not just for the keyboard... */ | ||||||
| /* this is for sliding stuff */ | /* this is for sliding stuff */ | ||||||
|  | |||||||
| @ -1217,6 +1217,10 @@ button:hover { | |||||||
| 	color: silver; | 	color: silver; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | .overlay-block .dialog .choice .item { | ||||||
|  | 	text-align: left; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /************************************************************ Help ***/ | /************************************************************ Help ***/ | ||||||
|  | |||||||
							
								
								
									
										27
									
								
								ui/ui.js
									
									
									
									
									
								
							
							
						
						
									
										27
									
								
								ui/ui.js
									
									
									
									
									
								
							| @ -978,9 +978,16 @@ function sortImagesDialog(message){ | |||||||
| 	cfg = {} | 	cfg = {} | ||||||
| 	cfg[message] = [ | 	cfg[message] = [ | ||||||
| 		'Date (ascending)',  | 		'Date (ascending)',  | ||||||
| 		'Name (ascending)',  | 		'Date (descending)',  | ||||||
| 		'Date (decending)',  | 
 | ||||||
| 		'Name (decending)' | 		'Sequence number (ascending)',  | ||||||
|  | 		'Sequence number (descending)', | ||||||
|  | 
 | ||||||
|  | 		'Sequence number with overflow (ascending)',  | ||||||
|  | 		'Sequence number with overflow (descending)', | ||||||
|  | 
 | ||||||
|  | 		'File name (ascending)',  | ||||||
|  | 		'File name (descending)' | ||||||
| 	] | 	] | ||||||
| 
 | 
 | ||||||
| 	formDialog(null, '',  | 	formDialog(null, '',  | ||||||
| @ -990,10 +997,20 @@ function sortImagesDialog(message){ | |||||||
| 		.done(function(res){ | 		.done(function(res){ | ||||||
| 			res = res[message] | 			res = res[message] | ||||||
| 
 | 
 | ||||||
| 			if(/Date/.test(res)){ | 			if(/Date/i.test(res)){ | ||||||
| 				var method = sortImagesByDate | 				var method = sortImagesByDate | ||||||
|  | 
 | ||||||
|  | 			} else if(/File name/i.test(res)){ | ||||||
|  | 				var method = sortImagesByFileNameXPStyle | ||||||
|  | 
 | ||||||
|  | 			} else if(/Sequence/i.test(res) && !/with overflow/.test(res)){ | ||||||
|  | 				var method = sortImagesByFileSeqOrName | ||||||
|  | 
 | ||||||
|  | 			} else if(/Sequence/i.test(res) && /with overflow/.test(res)){ | ||||||
|  | 				var method = sortImagesByFileNameSeqWithOverflow | ||||||
|  | 
 | ||||||
| 			} else { | 			} else { | ||||||
| 				var method = sortImagesByName | 				var method = sortImagesByFileName | ||||||
| 			} | 			} | ||||||
| 			if(/\(ascending\)/.test(res)){ | 			if(/\(ascending\)/.test(res)){ | ||||||
| 				var reverse = null | 				var reverse = null | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user