def map(image_path): """ Show map with pins for all jpg images in the given path :param image_path: String with path :return: - """ labels = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' labelIndex = 0 map = Map() images = list_jpg(image_path) exifs = images_get_exifs(image_path, images, report=True) # Sorted list by date, so the labels will be sorted names = list() for each in exifs: names.append((each['createdate'], each)) for e in sorted(names, key=lambda item: item[0]): if not e[1]['gps'] is None and not e[1]['gps']['lon'] is None: map.add_point((float(e[1]['gps']['lat']), float(e[1]['gps']['lon']), e[1]['name'], e[1]['title'], e[1]['description'], labels[labelIndex % len(labels)])) labelIndex += 1; if map.count() < 1: print('All {} images without geo locations'.format(str(len(images)))) return file_path = get_fow_root() + DIR_FOW + "/map.html" with open(file_path, "w") as out: print(map, file=out) webbrowser.open(file_path)
def move_corresponding_raws(jpg_dir, src_dir, dest_dir, dry_run): """ Moves all corresponding raws from source directory to destination directory. jpg_dir is the /jpg directory with corresponding jpg files. src_dir is the /row directory with raws to move. dest_dir is the target directory. """ # print('jpg=' + jpg_dir) # print('src=' + src_dir) # print('dst=' + dest_dir) jpgs = list_jpg(jpg_dir) # print(str(jpgs)) raws = list_raw(src_dir) # print(str(raws)) files = [ r for r in raws for j in jpgs if filename_get_name(r) == filename_get_name(j) ] if len(files) == 0: print('No RAWs to move.') return if dry_run: print('raw files to move (may already exists):') for each_file in files: print(str(each_file)) else: for each_file in files: os.rename(src_dir + '/' + each_file, dest_dir + '/' + each_file)
def analyse(_task, _dest): """ Checks export to dest from given task. task: dictionary with keys 'task' (foldername/taskname), 'name' (task name), 'folder' (folder name) dest: String with absolut path Returns list with dict() for every source file, for instance: return [dict(name='image001.jpg', exists='true', src_time=1474878288.2156258, dst_time=1474878288.2156258)] or dst_time=None """ src_dir = task.get_task_path(task.get_actual()['task']) + '/' + DIR_FINAL files = list_jpg(src_dir) # for file in files: # print('export_analyse() file=' + str(file) + ' ' # + time_readable(os.path.getatime(src_dir + '/' + file))) ret = [] for file in files: exists = os.path.exists(_dest + '/' + file) if exists: dst_time = os.path.getatime(_dest + '/' + file) else: dst_time = None ret.append( dict(name=file, exists=exists, src_time=os.path.getatime(src_dir + '/' + file), dst_time=dst_time)) # print('export_analyse() ret=' + str(ret)) return ret
def map(image_path): """ Show map with pins for all jpg images in the given path :param image_path: String with path :return: - """ labels = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' labelIndex = 0 map = Map() images = list_jpg(image_path) exifs = images_get_exifs(image_path, images, report=True) # Sorted list by date, so the labels will be sorted names = list() for each in exifs: names.append((each['createdate'], each)) for e in sorted(names, key=lambda item: item[0]): if not e[1]['gps'] is None and not e[1]['gps']['lon'] is None: map.add_point( (float(e[1]['gps']['lat']), float(e[1]['gps']['lon']), e[1]['name'], e[1]['title'], e[1]['description'], labels[labelIndex % len(labels)])) labelIndex += 1 if map.count() < 1: print('All {} images without geo locations'.format(str(len(images)))) return file_path = get_fow_root() + DIR_FOW + "/map.html" with open(file_path, "w") as out: print(map, file=out) webbrowser.open(file_path)
def move_corresponding_raws(jpg_dir, src_dir, dest_dir, dry_run): """ Moves all corresponding raws from source directory to destination directory. jpg_dir is the /jpg directory with corresponding jpg files. src_dir is the /row directory with raws to move. dest_dir is the target directory. """ # print('jpg=' + jpg_dir) # print('src=' + src_dir) # print('dst=' + dest_dir) jpgs = list_jpg(jpg_dir) # print(str(jpgs)) raws = list_raw(src_dir) # print(str(raws)) files = [r for r in raws for j in jpgs if filename_get_name(r) == filename_get_name(j)] if len(files) == 0: print('No RAWs to move.') return if dry_run: print('raw files to move (may already exists):') for each_file in files: print(str(each_file)) else: for each_file in files: os.rename(src_dir + '/' + each_file, dest_dir + '/' + each_file)
def analyse(track_path, image_path, write_path): """ Analyses for gps command for all image files in the given image_path. Tracks will be searched in track_path. Both directories should exist and should be accessible; but they can be empty. Subdirectories are not supported, neither for tracks, nor for images. Returns a list with a dict for every image file. List can be empty. Supported image file types are: jpg, raw and videos; it will be always search for every image type. Other files will be untouched (XMP, tiff). Supported track files are: gpx, tcx. Example with explanations: dict=(track_path=track_path, image_path=image_path, files= [dict=( image_name='img001.raf', # name of the image file image_gps= dict=(lat=123, lon=234) # actual image file location, can be None tracks=['2017-03-05.gpx', ...], # list with names of the track file, can be None dict=(...), ... ] """ ret = dict(track_path=track_path, image_path=image_path, files=[], existing_track_files=[]) images = list_video(image_path) images.extend(list_jpg(image_path)) # Load all gps files gpx_files = os.listdir(track_path) patterns = [] # for each in images: # ret['files'].append(dict(image_name=each)) exifs = images_get_exifs(image_path, images, True) existing_track_files = [] # print("anlyse() exifs={}".format(str(exifs))) for each in exifs: # print("analyse() {} {}".format(str(each['name']), str(each['createdate']))) if not each['createdate'] is None: (date, time) = each['createdate'].split(" ", 1) (y,m,d) = date.split(':') # print("analyse() {}-{}-{}".format(str(y), str(m), str(d))) # patterns.append(".*{0}.?{1}.?{2}.*\.gpx".format(y, m, d)) pattern = re.compile(".*{0}.?{1}.?{2}.*\.(tcx|gpx)".format(y, m, d)) # print("analyse() {0} track_files={1}".format(each['name'], str(track_files))) track_files = [f for f in gpx_files if not pattern.match(f) is None] # Find existing track files, that would be overwritten if write_path is not None: for dest in os.listdir(write_path): for src in (t for t in track_files if t == dest): existing_track_files.append(src) # print("analyse() exists={}".format(src)) ret['files'].append(dict(image_name=each['name'], image_gps=each['gps'], tracks=track_files)) ret['existing_track_files'] = list(frozenset(existing_track_files)) # print("analyse() ret={}".format(ret)) return ret
def check_images(path, criteria): """ Try to find the images to change. Checks criteria and prints a message in error case. :param path: :param criteria: String with eihter a number or a filename to select an image. Can be "all" to select all images in the actual task final dir. An empty string will be interpreted as '1' (first image) :return: A list with file names (like os.listdir) or, in error case, None """ all_files = list_jpg(path) # print("check_images {}".format(str(all_files))) if criteria == "all": return all_files if len(all_files) == 0: print("No images found in {}".format(str(path))) return None # Convenience for most cases if criteria is None: criteria = "1" # Select by number if re.match("^\d*$", criteria): nr = int(criteria) if nr < 1 or nr > len(all_files): print("Image nr doesn't match a file (must between {} and {})".format(str(1), str(len(all_files)))) return None return [all_files[nr - 1]] # Criteria can be a file name for file in (f for f in all_files if f == criteria): return [file] # Unexpected criteria print("Criteria '{}' invalid. Must be either a number, an existing file name or 'all'".format(str(criteria))) return None
def analyse(_task, _dest): """ Checks export to dest from given task. task: dictionary with keys 'task' (foldername/taskname), 'name' (task name), 'folder' (folder name) dest: String with absolut path Returns list with dict() for every source file, for instance: return [dict(name='image001.jpg', exists='true', src_time=1474878288.2156258, dst_time=1474878288.2156258)] or dst_time=None """ src_dir = task.get_task_path(task.get_actual()['task']) + '/' + DIR_FINAL files = list_jpg(src_dir) # for file in files: # print('export_analyse() file=' + str(file) + ' ' # + time_readable(os.path.getatime(src_dir + '/' + file))) ret = [] for file in files: exists = os.path.exists(_dest + '/' + file) if exists: dst_time = os.path.getatime(_dest + '/' + file) else: dst_time = None ret.append(dict( name=file, exists=exists, src_time=os.path.getatime(src_dir + '/' + file), dst_time=dst_time )) # print('export_analyse() ret=' + str(ret)) return ret
def analyse(_src, _dest_root): """ Checks load from external source tree to 00_Import sub directories jpg, raw and video. _src - absolut path to external root directory _dest - root directory for destination's sub Returns dict for every source file type jpg, raw and video. Every dict has a list with an dict for every file with fields file - file name path - absolut path of the source file time - timestamp of the source file exist - True, if file exists in destination directory desttime - None, if exist is None. Otherwise timestamp of dest file For instance: { 'jpg' : [ { 'file' : 'img34.jpg', 'path' : 'loadtest/DCIM/0001' 'time' : 1485803027.9297857 'exist' : False 'desttime': False}', ...], 'raw' : [...], 'video': [...] } """ # print('load_analyse() _src={0}'.format(_src)) dest_jpg = '{0}/{1}'.format(_dest_root, DIR_JPG) dest_raw = '{0}/{1}'.format(_dest_root, DIR_RAW) dest_video = '{0}/{1}'.format(_dest_root, DIR_VIDEO) files_jpg = list_jpg(dest_jpg) files_raw = list_raw(dest_raw) files_video = list_video(dest_video) values = dict(jpg=[], raw=[], video=[]) scan_tree(_src, values) # print('load_analyse() files_video={0}'.format(str(files_video))) # Add existing info for each_value in values['jpg']: # print('each_value {0}'.format(str(each_value))) each_value['exist'] = False each_value['desttime'] = None for each in [e for e in files_jpg if each_value['file'] == e]: each_value['exist'] = True each_value['desttime'] = os.path.getatime('{0}/{1}'.format( dest_jpg, each)) for each_value in values['raw']: # print('each_value {0}'.format(str(each_value))) each_value['exist'] = False each_value['desttime'] = None for each in [e for e in files_raw if each_value['file'] == e]: each_value['exist'] = True each_value['desttime'] = os.path.getatime('{0}/{1}'.format( dest_raw, each)) for each_value in values['video']: # print('each_value {0}'.format(str(each_value))) each_value['exist'] = False each_value['desttime'] = None for each in [e for e in files_video if each_value['file'] == e]: each_value['exist'] = True each_value['desttime'] = os.path.getatime('{0}/{1}'.format( dest_video, each)) # print('values {0}'.format(str(values))) return values
def cmd_export(cmd_list): """ Copy finals to external destinations. """ # 0: No param allowed, 1: param optional, 2: param obligatory # if not checkArgs(_arg_dict, # {'-t': 0, '--test': 0, '-p': 2, '--path': 2}): # return atom_path = dict(name='path', short='p', args=MANDATORY_PARAM) atom_force = dict(name='force', short='f', args=NONE_PARAM) atom_test = dict(name='test', short='t', args=NONE_PARAM) atom_none = dict(name='', short='', args=MANDATORY_PARAM) ret = check_rules(cmd_list, [[ dict(atom=atom_path, obligat=True), dict(atom=atom_force, obligat=False), dict(atom=atom_test, obligat=False) ], [ dict(atom=atom_none, obligat=True), dict(atom=atom_force, obligat=False), dict(atom=atom_test, obligat=False) ]]) if ret['message'] is not None: return # Get destination if 'path' in ret['options']: destination = ret['options']['path'] else: try: destination = config.read_pickle()[plump.EXPORT_PREFIX + '.' + ret['options']['']] except: print( "Destination value not defined. Create it with config -s='export.{}' first." .format(ret['options'][''])) return if destination is None: print('Destination not valid. See "help export".') return # Extract task specific subdirectory {1} or {2}, if given m = re.compile('(.*)(/{[12]}/?)').match(destination) # Direct path if m is None: if not os.path.exists(destination): print('Destination directory not reachable: ' + destination) return # Task specific path else: root_dir = m.group(1) if os.path.exists(m.group(1)): # Resolve subdirectory placeholder: task name if destination.endswith(('{1}', '{1}/')): destination = root_dir + '/' + task.get_actual()['name'] # Resolve subdirectory placeholder: folder + task name elif destination.endswith(('{2}', '{2}/')): destination = root_dir + '/' + task.get_actual()['task'] else: print('Destination root directory not reachable: ' + root_dir) return print('destination={}'.format(destination)) if not task.check_actual(): return src_dir = task.get_actual()['task'] + '/' + plump.DIR_FINAL src_path = task.get_task_path(src_dir) files = plump.list_jpg(src_path) # [dict(name='image001.jpg', exists='true')] analysis = export.analyse(task.get_actual(), destination) if 'test' in ret['options']: export.test(analysis, src_dir, destination) return # export --force if 'force' in ret['options']: print( str(len(files)) + ' images in ' + task.get_actual()['task'] + '/' + plump.DIR_FINAL) print('Destination: ' + destination) export.copy(analysis, src_path, destination) # export else: exists = False for item in analysis: if item['exists']: exists = True if exists: print('Files would be overwritten! ' + 'Use --test to list the file(s) ' + 'or use --force to overwrite the image(s). ') else: print( str(len(files)) + ' images in ' + task.get_actual()['task'] + '/' + plump.DIR_FINAL) print('Destination: ' + destination) export.copy(analysis, src_path, destination)
def analyse(track_path, image_path, write_path): """ Analyses for gps command for all image files in the given image_path. Tracks will be searched in track_path. Both directories should exist and should be accessible; but they can be empty. Subdirectories are not supported, neither for tracks, nor for images. Returns a list with a dict for every image file. List can be empty. Supported image file types are: jpg, raw and videos; it will be always search for every image type. Other files will be untouched (XMP, tiff). Supported track files are: gpx, tcx. Example with explanations: dict=(track_path=track_path, image_path=image_path, files= [dict=( image_name='img001.raf', # name of the image file image_gps= dict=(lat=123, lon=234) # actual image file location, can be None tracks=['2017-03-05.gpx', ...], # list with names of the track file, can be None dict=(...), ... ] """ ret = dict(track_path=track_path, image_path=image_path, files=[], existing_track_files=[]) images = list_video(image_path) images.extend(list_jpg(image_path)) # Load all gps files gpx_files = os.listdir(track_path) patterns = [] # for each in images: # ret['files'].append(dict(image_name=each)) exifs = images_get_exifs(image_path, images, True) existing_track_files = [] # print("anlyse() exifs={}".format(str(exifs))) for each in exifs: # print("analyse() {} {}".format(str(each['name']), str(each['createdate']))) if not each['createdate'] is None: (date, time) = each['createdate'].split(" ", 1) (y, m, d) = date.split(':') # print("analyse() {}-{}-{}".format(str(y), str(m), str(d))) # patterns.append(".*{0}.?{1}.?{2}.*\.gpx".format(y, m, d)) pattern = re.compile(".*{0}.?{1}.?{2}.*\.(tcx|gpx)".format( y, m, d)) # print("analyse() {0} track_files={1}".format(each['name'], str(track_files))) track_files = [ f for f in gpx_files if not pattern.match(f) is None ] # Find existing track files, that would be overwritten if write_path is not None: for dest in os.listdir(write_path): for src in (t for t in track_files if t == dest): existing_track_files.append(src) # print("analyse() exists={}".format(src)) ret['files'].append( dict(image_name=each['name'], image_gps=each['gps'], tracks=track_files)) ret['existing_track_files'] = list(frozenset(existing_track_files)) # print("analyse() ret={}".format(ret)) return ret
def analyse(src_path, dest_path): """ Analyses for renaming command for all image files in the given path. Returns a list with a dict for every file. List can be empty. Supported image file types are: jpg, raw and videos; it will be always search for every image type. Other files will be untouched (XMP, tiff). Example with explanations: dict=(src_path=src_path, dest_path=dest_path, files= [dict=( subdir='RAW' old_name='img001.raf', #file name in src_path new_name='20161131-123456-img001.raf', #new image name exists=True), #False, if no file name conflict #in dest_path dict=(...), ... ] """ ret = [] subdir = DIR_JPG files = list_jpg(src_path + '/' + subdir) index = 0 progress = progress_prepare(len(files), 'Processing', subdir) for each in files: # print(str(image_get_time(path))) index += 1 sys.stdout.write(progress['back'] + progress['formatting'].format(str(index))) sys.stdout.flush() old_name = each time_str = image_get_time(src_path + '/' + subdir + '/' + each) if time_str is None: new_name = old_name else: new_name = time_str + '-' + old_name if os.path.exists(dest_path + '/' + subdir + '/' + new_name): exists = True else: exists = False ret.append(dict(subdir=subdir, old_name=old_name, new_name=new_name, exists=exists)) sys.stdout.write('\n') subdir = DIR_RAW files = list_raw(src_path + '/' + subdir) index = 0 progress = progress_prepare(len(files), 'Processing', subdir) for each in files: # print(str(image_get_time(path))) index += 1 sys.stdout.write(progress['back'] + progress['formatting'].format(str(index))) sys.stdout.flush() old_name = each time_str = image_get_time(src_path + '/' + subdir + '/' + each) if time_str is None: new_name = old_name else: new_name = time_str + '-' + old_name if os.path.exists(dest_path + '/' + subdir + '/' + new_name): exists = True else: exists = False ret.append(dict(subdir=subdir, old_name=old_name, new_name=new_name, exists=exists)) sys.stdout.write('\n') subdir = DIR_VIDEO files = list_video(src_path + '/' + subdir) index = 0 progress = progress_prepare(len(files), 'Processing', subdir) for each in files: # print(str(image_get_time(path))) index += 1 sys.stdout.write(progress['back'] + progress['formatting'].format(str(index))) sys.stdout.flush() old_name = each time_str = video_get_time(src_path + '/' + subdir + '/' + each) if time_str is None: new_name = old_name else: new_name = time_str + '-' + old_name if os.path.exists(dest_path + '/' + subdir + '/' + new_name): exists = True else: exists = False ret.append(dict(subdir=subdir, old_name=old_name, new_name=new_name, exists=exists)) sys.stdout.write('\n') return dict(src_path=src_path, dest_path=dest_path, files=ret)
def cmd_export(cmd_list): """ Copy finals to external destinations. """ # 0: No param allowed, 1: param optional, 2: param obligatory # if not checkArgs(_arg_dict, # {'-t': 0, '--test': 0, '-p': 2, '--path': 2}): # return atom_path = dict(name='path', short='p', args=MANDATORY_PARAM) atom_force = dict(name='force', short='f', args=NONE_PARAM) atom_test = dict(name='test', short='t', args=NONE_PARAM) atom_none = dict(name='', short='', args=MANDATORY_PARAM) ret = check_rules(cmd_list, [ [ dict(atom=atom_path, obligat=True), dict(atom=atom_force, obligat=False), dict(atom=atom_test, obligat=False) ], [ dict(atom=atom_none, obligat=True), dict(atom=atom_force, obligat=False), dict(atom=atom_test, obligat=False) ] ]) if ret['message'] is not None: return # Get destination if 'path' in ret['options']: destination = ret['options']['path'] else: try: destination = config.read_pickle()[plump.EXPORT_PREFIX + '.' + ret['options']['']] except: print("Destination value not defined. Create it with config -s='export.{}' first." .format(ret['options'][''])) return if destination is None: print('Destination not valid. See "help export".') return # Extract task specific subdirectory {1} or {2}, if given m = re.compile('(.*)(/{[12]}/?)').match(destination) # Direct path if m is None: if not os.path.exists(destination): print('Destination directory not reachable: ' + destination) return # Task specific path else: root_dir = m.group(1) if os.path.exists(m.group(1)): # Resolve subdirectory placeholder: task name if destination.endswith(('{1}', '{1}/')): destination = root_dir + '/' + task.get_actual()['name'] # Resolve subdirectory placeholder: folder + task name elif destination.endswith(('{2}', '{2}/')): destination = root_dir + '/' + task.get_actual()['task'] else: print('Destination root directory not reachable: ' + root_dir) return print('destination={}'.format(destination)) if not task.check_actual(): return src_dir = task.get_actual()['task'] + '/' + plump.DIR_FINAL src_path = task.get_task_path(src_dir) files = plump.list_jpg(src_path) # [dict(name='image001.jpg', exists='true')] analysis = export.analyse(task.get_actual(), destination) if 'test' in ret['options']: export.test(analysis, src_dir, destination) return # export --force if 'force' in ret['options']: print(str(len(files)) + ' images in ' + task.get_actual()['task'] + '/' + plump.DIR_FINAL) print('Destination: ' + destination) export.copy(analysis, src_path, destination) # export else: exists = False for item in analysis: if item['exists']: exists = True if exists: print('Files would be overwritten! ' + 'Use --test to list the file(s) ' + 'or use --force to overwrite the image(s). ') else: print(str(len(files)) + ' images in ' + task.get_actual()['task'] + '/' + plump.DIR_FINAL) print('Destination: ' + destination) export.copy(analysis, src_path, destination)