You've already forked photo-importer
							
							
				mirror of
				https://github.com/sashacmc/photo-importer.git
				synced 2025-10-30 23:37:37 +02:00 
			
		
		
		
	Rotator added. File time src order config added.
This commit is contained in:
		| @@ -9,8 +9,9 @@ class Config(object): | ||||
|     DEFAULTS = { | ||||
|         'main': { | ||||
|             'out_time_format': '%%Y-%%m-%%d_%%H-%%M-%%S', | ||||
|             'use_exif_first': True, | ||||
|             'time_src': 'exif,name,attr', | ||||
|             'remove_garbage': True, | ||||
|             'threads_count': 2, | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   | ||||
							
								
								
									
										37
									
								
								fileprop.py
									
									
									
									
									
								
							
							
						
						
									
										37
									
								
								fileprop.py
									
									
									
									
									
								
							| @@ -54,17 +54,7 @@ class FileProp(object): | ||||
|  | ||||
|         self.__type = self.__type_by_ext(ext) | ||||
|  | ||||
|         if self.__type == self.IMAGE: | ||||
|             if self.__config['main']['use_exif_first']: | ||||
|                 self.__time = self.__time_by_exif(fullname) | ||||
|                 if self.__time is None: | ||||
|                     self.__time = self.__time_by_name(fname) | ||||
|             else: | ||||
|                 self.__time = self.__time_by_name(fname) | ||||
|                 if self.__time is None: | ||||
|                     self.__time = self.__time_by_exif(fullname) | ||||
|         else: | ||||
|             self.__time = self.__time_by_name(fname) | ||||
|         self.__time = self.__time(fullname, fname) | ||||
|  | ||||
|         out_name = self.out_name() | ||||
|         if out_name: | ||||
| @@ -79,6 +69,21 @@ class FileProp(object): | ||||
|             logging.warning('Unknown ext: ' + ext) | ||||
|             return self.OTHER | ||||
|  | ||||
|     def __time(self, fullname, name): | ||||
|         for src in self.__config['main']['time_src'].split(','): | ||||
|             time = None | ||||
|             if src == 'exif': | ||||
|                 time = self.__time_by_exif(fullname) | ||||
|             elif src == 'name': | ||||
|                 time = self.__time_by_name(name) | ||||
|             elif src == 'attr': | ||||
|                 time = self.__time_by_attr(name) | ||||
|             else: | ||||
|                 raise Exception('Wrong time_src: ' + src) | ||||
|  | ||||
|             if time: | ||||
|                 return time | ||||
|  | ||||
|     def __time_by_name(self, fname): | ||||
|         for exp, fs in self.DATE_REX: | ||||
|             mat = exp.findall(fname) | ||||
| @@ -95,16 +100,22 @@ class FileProp(object): | ||||
|         return None | ||||
|  | ||||
|     def __time_by_exif(self, fullname): | ||||
|         if self.__type != self.IMAGE: | ||||
|             return None | ||||
|  | ||||
|         try: | ||||
|             with open(fullname, 'rb') as f: | ||||
|                 tags = exifread.process_file(f) | ||||
|                 strtime = tags['EXIF DateTimeOriginal'].values | ||||
|                 return datetime.datetime.strptime(strtime, '%Y:%m:%d %H:%M:%S') | ||||
|         except (OSError, KeyError): | ||||
|         except (FileNotFoundError, KeyError): | ||||
|             return None | ||||
|  | ||||
|     def __time_by_attr(self, fullname): | ||||
|         self.__time = time.localtime(os.stat(fullname)[stat.ST_MTIME]) | ||||
|         try: | ||||
|             self.__time = time.localtime(os.stat(fullname)[stat.ST_MTIME]) | ||||
|         except (FileNotFoundError, KeyError): | ||||
|             return None | ||||
|  | ||||
|     def out_name(self): | ||||
|         if self.__time: | ||||
|   | ||||
							
								
								
									
										77
									
								
								rotate.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										77
									
								
								rotate.py
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,77 @@ | ||||
| #!/usr/bin/python3 | ||||
|  | ||||
| import logging | ||||
| import subprocess | ||||
| import concurrent.futures | ||||
|  | ||||
| import config | ||||
|  | ||||
|  | ||||
| class Rotator(object): | ||||
|     def __init__(self, config, filenames): | ||||
|         self.__config = config | ||||
|         self.__filenames = filenames | ||||
|         self.__processed = 0 | ||||
|         self.__good = 0 | ||||
|         self.__errors = 0 | ||||
|  | ||||
|     def run(self): | ||||
|         tc = int(self.__config['main']['threads_count']) | ||||
|         with concurrent.futures.ThreadPoolExecutor(max_workers=tc) as executor: | ||||
|  | ||||
|             futures = { | ||||
|                 executor.submit(self.__process, fn): | ||||
|                 fn for fn in self.__filenames} | ||||
|  | ||||
|             for future in concurrent.futures.as_completed(futures): | ||||
|                 self.__processed += 1 | ||||
|                 if future.result(): | ||||
|                     self.__good += 1 | ||||
|                 else: | ||||
|                     self.__errors += 1 | ||||
|  | ||||
|     def __process(self, filename): | ||||
|         ok = False | ||||
|         try: | ||||
|             cmd = 'exiftran -aip %s' % filename | ||||
|             p = subprocess.Popen( | ||||
|                 cmd, | ||||
|                 shell=True, | ||||
|                 stdout=subprocess.PIPE, | ||||
|                 stderr=subprocess.PIPE).stderr | ||||
|  | ||||
|             error = '' | ||||
|             while 1: | ||||
|                 line = p.readline().decode("utf-8") | ||||
|                 if not line: | ||||
|                     break | ||||
|  | ||||
|                 if line.startswith('processing '): | ||||
|                     ok = True | ||||
|                 else: | ||||
|                     ok = False | ||||
|                     error += line | ||||
|  | ||||
|             if error != '': | ||||
|                 logging.error('exiftran (%s) error: %s' % (filename, error)) | ||||
|  | ||||
|         except Exception as ex: | ||||
|             logging.error('Rotator process exeption: %s' % ex) | ||||
|  | ||||
|         return ok | ||||
|  | ||||
|     def status(self): | ||||
|         return ( | ||||
|             len(self.__filenames), | ||||
|             self.__processed, | ||||
|             self.__good, | ||||
|             self.__errors) | ||||
|  | ||||
|  | ||||
| if __name__ == '__main__': | ||||
|     import sys | ||||
|  | ||||
|     rot = Rotator(config.Config(False), sys.argv[1:]) | ||||
|     rot.run() | ||||
|  | ||||
|     print(rot.status()) | ||||
		Reference in New Issue
	
	Block a user