def sanitize_filename(folder=r"", posttags_to_end: List[str] = None, onlyprint=False): """ sanitize order of Scene and Process tags sanitize counter to be split by $ sanitize sub process names added by a external program to by concat to main processname (only Hugin) :param folder: optional regex for restrict to folders :param posttags_to_end: optional for resorting special posttags to end :param onlyprint: if true, renaming will only printed to log and no files are renamed, good for testing :return: """ inpath = os.getcwd() for (dirpath, dirnames, filenames) in os.walk(inpath): if is_invalid_path(dirpath, regex=folder): continue for filename in (filenames + dirnames): filename = filename.replace("panorama", "PANO") filenameAccessor = FilenameAccessor(filename) _sanitize_posttags(filenameAccessor, posttags_to_end) _sanitize_process_counter(filenameAccessor) _sanitize_pano(filenameAccessor) filename_new = filenameAccessor.sorted_filename() if not filename == filename_new: log().info("rename: %s to %s", filename, filename_new) if not onlyprint: renameInPlace(dirpath, filename, filename_new)
def create_counters_csv_per_dir(): """ extract counter from the file name write a csv file with those counters for each directory This csv can be modified to be used with :func:`write_exif_using_csv` If you want to modify it with EXCEL or Calc take care to import all columns of the csv as text. """ log_function_call(create_tags_csv_per_dir.__name__) inpath = os.getcwd() tag_set_names = OrderedSet() out_filename = get_info_dir("tags_counters.csv") csvfile, writer = fileop.create_csv_writer(out_filename, [ "directory", "name_main", "name_part", "first", "last", "tags3", "description" ]) for (dirpath, dirnames, filenames) in os.walk(inpath): if not inpath == dirpath: continue for dirname in dirnames: filenameAccessors = [ FilenameAccessor(filename) for filename in get_plain_filenames_of_type( image_types, dirpath, dirname) ] if len(filenameAccessors) == 0: continue _add_counter_csv_entries(dirname, filenameAccessors, tag_set_names) writer.writerows(tag_set_names) csvfile.close()
def create_tags_csv(location: str = ""): """ extract tags from the file name write a csv file with those tags :param location: optional content of directory column This csv can be modified to be used with :func:`write_exif_using_csv` or :func:`placeinfo.write_infos` If you want to modify it with EXCEL or Calc take care to import all columns of the csv as text. """ inpath = os.getcwd() tag_set = OrderedSet() tag_set_names = OrderedSet() out_filename = get_info_dir("tags_places.csv") tags_places_file, writer = fileop.create_csv_writer( out_filename, ["directory", "name_part"]) filenameAccessors = [ FilenameAccessor(filename) for filename in get_plain_filenames_of_type(image_types, inpath) ] for fileNameAccessor in filenameAccessors: for tag in fileNameAccessor.tags(): tag_set.add(tag) writeToFile(get_info_dir("tags.txt"), location + "\n\t" + "\n\t".join(tag_set) + "\n") for tag in tag_set: tag_set_names.add((location, tag)) writer.writerows(tag_set_names) tags_places_file.close()
def _sanitize_process_counter(filenameAccessor: FilenameAccessor): processes_new = [] for process_mode in filenameAccessor.processes: if not "$" in process_mode: match = re.search(r'([^\d]+)(\d.*)', process_mode) if match: process_mode = match.group(1) + "$" + match.group(2) processes_new.append(process_mode) filenameAccessor.processes = processes_new
def resize(size=(128, 128)): """ resize to icon like image :param size: size of resulting image """ log_function_call(resize.__name__, size) inpath = os.getcwd() dest = os.path.join(inpath, "SMALL") os.mkdir(dest) for (dirpath, dirnames, filenames) in os.walk(inpath): if is_invalid_path(dirpath, blacklist=["SMALL"]): continue for filename in filenames: if not file_has_ext(filename, ('.JPG', ".jpg")): continue # Load the original image: accessor = FilenameAccessor(filename) img = Image.open(os.path.join(dirpath, filename)) img.thumbnail(size, Image.ANTIALIAS) accessor.processes.append("SMALL") outfile = os.path.join(dest, accessor.sorted_filename()) img.save(outfile, 'JPEG', quality=90)
def copy_exif_via_mainname(origin: str, target: str, overwriteDateTime: bool = False, file_types: Iterable = settings.image_types): """ copy exif information from files in directory origin to target files are matched via main name -> processed files can get exif information of original files :param overwriteDateTime: whether to overwrite already exiting "Date/Time Original" :param origin: where exif infos should be read :param target: where exif infos should be written to :param file_types: of target files, default: all image types """ log_function_call(copy_exif_via_mainname.__name__, origin, target) inpath = os.getcwd() target_dict = {} exclusion_tags = ["--PreviewImage", "--ThumbnailImage", "--Rating"] command = "-TagsFromFile" for (dirpath, dirnames, filenames) in os.walk(os.path.join(inpath, target)): if is_invalid_path(dirpath): continue filenames = filterFiles(filenames, file_types) for filename in filenames: if not overwriteDateTime: tagDict = read_exiftag(dirpath, filename) if hasDateTime(tagDict): continue main = FilenameAccessor(filename).mainname() target_dict.setdefault(main, []).append(os.path.join(dirpath, filename)) for (dirpath, dirnames, filenames) in os.walk(os.path.join(inpath, origin)): if is_invalid_path(dirpath): continue filenames = filterFiles(filenames, settings.image_types) for filename in filenames: main = FilenameAccessor(filename).mainname() if not main in target_dict: continue if filename in [os.path.basename(target_file) for target_file in target_dict[main]]: continue orgin_file = os.path.join(dirpath, filename) for target_file in target_dict[main]: commands = [command, orgin_file, target_file] call_exiftool_direct(exclusion_tags + commands) del target_dict[main]
def move_each_pretag_to_folder(): """ """ log_function_call(move_each_pretag_to_folder.__name__) inpath = os.getcwd() for (dirpath, dirnames, filenames) in os.walk(inpath): if is_invalid_path(dirpath): continue for filename in filenames: filenameAccessor = FilenameAccessor(filename) if not filenameAccessor.pre in dirpath: move(filename, dirpath, os.path.join(dirpath, filenameAccessor.pre)) if len(filenameAccessor.primtags ) > 0 and not filenameAccessor.primtags[0] in dirpath: move(filename, dirpath, os.path.join(dirpath, *filenameAccessor.primtags))
def _sanitize_pano(filenameAccessor: FilenameAccessor): matches = [ tag for tag in filenameAccessor.processes if tag.startswith("PANO") ] if not matches: return pano_name = matches[0] pano_split = pano_name.split("$") pano_newname = pano_split[0] pano_modi = ["blended", "fused", "hdr"] for pano_modus in pano_modi: if pano_modus in filenameAccessor.posttags: pano_newname += "-" + pano_modus filenameAccessor.posttags.remove(pano_modus) if len(pano_split) > 0: pano_newname = "$".join([pano_newname] + pano_split[1:]) filenameAccessor.processes.remove(matches[0]) filenameAccessor.processes = [pano_newname] + filenameAccessor.processes
def create_names_csv_per_dir(start_after_dir=''): """ extract names from the file path write a csv file with those names for each directory This csv can be modified to be used with :func:`write_exif_using_csv` If you want to modify it with EXCEL or Calc take care to import all columns of the csv as text. """ log_function_call(create_names_csv_per_dir.__name__) inpath = os.getcwd() tag_set_names = OrderedSet() out_filename = get_info_dir("tags_names.csv") csvfile, writer = fileop.create_csv_writer( out_filename, ["directory", "name_main", "tags"]) for (dirpath, dirnames, filenames) in os.walk(inpath): if is_invalid_path(dirpath): continue filenameAccessors = [ FilenameAccessor(filename) for filename in filterFiles(filenames, image_types) ] if len(filenameAccessors) == 0: continue tags = [] found = False for part in dirpath.split(os.sep): if found: tags += part.split(', ') else: found = part == start_after_dir filenameAccessorLast = filenameAccessors[0] tag_set_names.add( (", ".join(tags), filenameAccessorLast.pre, ', '.join(OrderedSet(tags + [filenameAccessorLast.pre])))) for filenameAccessor in filenameAccessors[1:]: if not filenameAccessor.pre == filenameAccessorLast.pre: tag_set_names.add( (", ".join(tags), filenameAccessor.pre, ', '.join(OrderedSet(tags + [filenameAccessor.pre])))) filenameAccessorLast = filenameAccessor writer.writerows(tag_set_names) csvfile.close()
def create_tags_csv_per_dir(): """ extract tags from the file name write a csv file with those tags and group them by toplevel directory This csv can be modified to be used with :func:`write_exif_using_csv` or :func:`placeinfo.write_infos` If you want to modify it with EXCEL or Calc take care to import all columns of the csv as text. """ log_function_call(create_tags_csv_per_dir.__name__) inpath = os.getcwd() tag_set_names = OrderedSet() out_filename = get_info_dir("tags_per_dir.csv") tags_places_file, writer = fileop.create_csv_writer( out_filename, ["directory", "name_part"]) for (dirpath, dirnames, filenames) in os.walk(inpath): if not inpath == dirpath: continue for dirname in dirnames: tag_set = OrderedSet() filenameAccessors = [ FilenameAccessor(filename) for filename in get_plain_filenames_of_type( image_types, dirpath, dirname) ] if len(filenameAccessors) == 0: continue for fileNameAccessor in filenameAccessors: for tag in fileNameAccessor.tags(): tag_set.add(tag) writeToFile(get_info_dir("tags.txt"), dirname + "\n\t" + "\n\t".join(tag_set) + "\n") dirname_split = dirname.split("_") subnames = [ subname for subname in dirname_split if not subname.isnumeric() ] dirname = "_".join(subnames) for tag in tag_set: tag_set_names.add((dirname, tag)) writer.writerows(tag_set_names) tags_places_file.close()
def test_sorting(self): filenameAccessor = FilenameAccessor( "ISL190727_250_HDR-Ls-Nb_Dettifoss_Selfoss_RET_PANO.jpg") self.assertEqual( "ISL190727_250_HDR-Ls-Nb_RET_PANO_Dettifoss_Selfoss.jpg", filenameAccessor.sorted_filename())