yrasdasda

This commit is contained in:
Geoffrey Frogeye 2022-06-09 18:42:02 +02:00
parent 1a8d1db86c
commit 95faa0c0ff
4 changed files with 274 additions and 25 deletions

114
config/scripts/camera_name_date Executable file
View file

@ -0,0 +1,114 @@
#!/usr/bin/env python3
"""
Same as picture_name_date
except it's tailored for OpenCamera.
It uses filenames, that way:
- Easier to get metadata
- JPG/DNG, MP4/SRT keep the same filename
"""
import argparse
import logging
import os
import re
import coloredlogs
log = logging.getLogger(__name__)
coloredlogs.install(level="DEBUG", fmt="%(levelname)s %(message)s", logger=log)
PATTERNS = [
re.compile( # OpenCamera
r"^(?P<type>IMG|VID)_"
# No TRIM. We don't want those as they're a short copy of an existing VID.
r"(?P<Y>\d\d\d\d)(?P<M>\d\d)(?P<D>\d\d)_"
r"(?P<h>\d\d)(?P<m>\d\d)(?P<s>\d\d)"
r"(?P<dup>_(\d+))?"
r"(?P<spec>_(PANO|HDR))?"
r"\.(?P<ext>jpg|dng|mp4|srt)$"
),
re.compile( # Samsung camera app (?)
r"(?P<Y>\d\d\d\d)(?P<M>\d\d)(?P<D>\d\d)_"
r"(?P<h>\d\d)(?P<m>\d\d)(?P<s>\d\d)"
r"\.(?P<ext>jpg|mp4)$"
),
re.compile( # Telegram Media Downloader photo
r"photo_"
r"(?P<Y>\d\d\d\d)-(?P<M>\d\d)-(?P<D>\d\d)_"
r"(?P<h>\d\d)-(?P<m>\d\d)-(?P<s>\d\d)"
r"(?P<dup>_\d{19})"
r"\.(?P<ext>jpg)$"
), # Time of publication, not time of photo!
re.compile( # Telegram Media Downloader video
r"video_"
r"(?P<Y>\d\d\d\d)-(?P<M>\d\d)-(?P<D>\d\d)_"
r"(?P<h>\d\d)-(?P<m>\d\d)-(?P<s>\d\d)"
r"(?P<dup>_\d{19})"
r"\.(?P<ext>mp4)$"
), # Time of publication, not time of video!
]
def main(args: argparse.Namespace) -> None:
for root, _, files in os.walk(args.dir):
for filename in files:
full_path = os.path.join(root, filename)
for pattern in PATTERNS:
match = re.match(pattern, filename)
if match:
break
else:
log.warning(f"{full_path} doesn't any pattern")
continue
# Build new filename
m = match.groupdict()
new_filename = (
f"{m['Y']}-{m['M']}-{m['D']}_"
f"{m['h']}-{m['m']}-{m['s']}"
f"{m.get('dup', '')}"
f"{m.get('spec', '')}"
f"{args.suffix}"
f".{m['ext']}"
)
new_path = os.path.join(args.dir, new_filename)
# TODO Allow keeping image in same folder
# Rename file
if full_path == new_path:
log.debug(f"{full_path} already at required filename")
continue
log.info(f"{full_path} →\t{new_path}")
if os.path.exists(new_path):
raise FileExistsError(f"{new_path} already exists!")
if not args.dry:
os.rename(full_path, new_path)
if __name__ == "__main__":
parser = argparse.ArgumentParser(
description="Rename OpenCamera files based on their dates"
)
parser.add_argument(
"dir",
metavar="DIRECTORY",
type=str,
default=".",
nargs="?",
help="Directory containing the pictures",
)
parser.add_argument(
"-d",
"--dry",
action="store_true",
help="Do not actually rename, just show old and new path",
)
parser.add_argument(
"-s",
"--suffix",
default="",
help="Text to add before the extension",
)
args = parser.parse_args()
main(args)

View file

@ -1,20 +1,22 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import argparse
import datetime
import logging
import os import os
import re import re
import typing import typing
import datetime
import PIL.ExifTags import coloredlogs
import PIL.Image import exifread
import progressbar import progressbar
EXTENSION_PATTERN = re.compile(r"\.JPE?G", re.I) log = logging.getLogger(__name__)
coloredlogs.install(level="DEBUG", fmt="%(levelname)s %(message)s", logger=log)
EXTENSION_PATTERN = re.compile(r"\.(JPE?G|DNG)", re.I)
COMMON_PATTERN = re.compile(r"(IMG|DSC[NF]?|100|P10|f|t)_?\d+", re.I) COMMON_PATTERN = re.compile(r"(IMG|DSC[NF]?|100|P10|f|t)_?\d+", re.I)
EXIF_TAG_NAME = "DateTimeOriginal" EXIF_TAG_ID = 0x9003 # DateTimeOriginal
EXIF_TAG_ID = list(PIL.ExifTags.TAGS.keys())[
list(PIL.ExifTags.TAGS.values()).index(EXIF_TAG_NAME)
]
EXIF_DATE_FORMAT = "%Y:%m:%d %H:%M:%S" EXIF_DATE_FORMAT = "%Y:%m:%d %H:%M:%S"
@ -23,7 +25,6 @@ def get_pictures(directory: str = ".", skip_renamed: bool = True) -> typing.Gene
for filename in files: for filename in files:
filename_trunk, extension = os.path.splitext(filename) filename_trunk, extension = os.path.splitext(filename)
# if extension.upper() not in ('.JPEG', '.JPG'):
if not re.match(EXTENSION_PATTERN, extension): if not re.match(EXTENSION_PATTERN, extension):
continue continue
if skip_renamed: if skip_renamed:
@ -33,23 +34,85 @@ def get_pictures(directory: str = ".", skip_renamed: bool = True) -> typing.Gene
yield full_path yield full_path
def main() -> None: def main(args: argparse.Namespace) -> None:
print("Counting files...") log.warning("Counting files...")
nb_imgs = len(list(get_pictures())) kwargs = {"directory": args.dir, "skip_renamed": args.skip_renamed}
print("Processing files...") log.warning("Processing files...")
iterator = progressbar.progressbar(get_pictures(), max_value=nb_imgs) if args.hide_bar:
iterator = get_pictures(**kwargs)
else:
nb_imgs = len(list(get_pictures(**kwargs)))
iterator = progressbar.progressbar(get_pictures(**kwargs), max_value=nb_imgs)
for full_path in iterator: for full_path in iterator:
img = PIL.Image.open(full_path) # Find date
exif_data = img._getexif() with open(full_path, 'rb') as fd:
if exif_data and EXIF_TAG_ID in exif_data: exif_data = exifread.process_file(fd)
date_raw = exif_data[EXIF_TAG_ID] if not exif_data:
date = datetime.datetime.strptime(date_raw, EXIF_DATE_FORMAT) log.warning(f"{full_path} does not have EXIF data")
new_name = date.isoformat().replace(":", "-") + ".jpg" # For NTFS for ifd_tag in exif_data.values():
print(full_path, new_name) if ifd_tag.tag == EXIF_TAG_ID:
os.rename(full_path, new_name) # TODO FOLDER date_raw = ifd_tag.values
img.close() break
else:
log.warning(f"{full_path} does not have required EXIF tag")
continue
date = datetime.datetime.strptime(date_raw, EXIF_DATE_FORMAT)
# Determine new filename
ext = os.path.splitext(full_path)[1].lower()
if ext == '.jpeg':
ext = '.jpg'
new_name = date.isoformat().replace(":", "-").replace("T", "_")
# First substitution is to allow images being sent to a NTFS filesystem
# Second substitution is for esthetics
new_path = os.path.join(args.dir, f"{new_name}{ext}")
# TODO Allow keeping image in same folder
i = 0
while os.path.exists(new_path):
if full_path == new_path:
break
log.debug(f"{full_path} already exists, incrementing")
i += 1
new_path = os.path.join(args.dir, f"{new_name}_{i}{ext}")
# Rename file
if full_path == new_path:
log.debug(f"{full_path} already at required filename")
continue
log.info(f"{full_path} →\t{new_path}")
if os.path.exists(new_path):
raise FileExistsError(f"Won't overwrite {new_path}")
if not args.dry:
os.rename(full_path, new_path)
if __name__ == "__main__": if __name__ == "__main__":
# TODO Arguments parsing parser = argparse.ArgumentParser(description="Rename images based on their dates")
main() parser.add_argument(
"dir",
metavar="DIRECTORY",
type=str,
default=".",
nargs="?",
help="Directory containing the pictures",
)
parser.add_argument(
"-d",
"--dry",
action="store_true",
help="Do not actually rename, just show old and new path",
)
parser.add_argument(
"-s",
"--skip-renamed",
action="store_true",
help="Skip images whose filename doesn't match usual camera output filenames.",
)
parser.add_argument(
"-b",
"--hide-bar",
action="store_true",
help="Do not show a progress bar. Also skip counting images",
)
args = parser.parse_args()
main(args)

68
config/scripts/raw_move_precomp Executable file
View file

@ -0,0 +1,68 @@
#!/usr/bin/env python3
"""
Same as picture_name_date
except it's tailored for OpenCamera.
It uses filenames, that way:
- Easier to get metadata
- JPG/DNG, MP4/SRT keep the same filename
"""
import argparse
import logging
import os
import coloredlogs
log = logging.getLogger(__name__)
coloredlogs.install(level="DEBUG", fmt="%(levelname)s %(message)s", logger=log)
RAW_EXTENSIONS = [".dng"]
PRECOMP_EXTENSIONS = [".jpg", ".jpeg"]
PRECOMP_DIRECTORY = ".precomp"
def main(args: argparse.Namespace) -> None:
for root, _, files in os.walk(args.dir):
for filename in files:
raw_path = os.path.join(root, filename)
basename, raw_ext = os.path.splitext(filename)
if raw_ext.lower() not in RAW_EXTENSIONS:
log.debug(f"{raw_path} isn't a RAW file")
continue
# TODO Search for upper case extension
for precomp_ext in PRECOMP_EXTENSIONS:
precomp_filename = basename + precomp_ext
precomp_path = os.path.join(root, precomp_filename)
if not os.path.exists(precomp_path):
continue
precomp_dir = os.path.join(root, PRECOMP_DIRECTORY)
precomp_dest = os.path.join(precomp_dir, precomp_filename)
log.info(f"{precomp_path} -> {precomp_dest} because of {raw_path}")
if not args.dry:
os.makedirs(precomp_dir, exist_ok=True)
os.rename(precomp_path, precomp_dest)
if __name__ == "__main__":
parser = argparse.ArgumentParser(
description="Move pre-composed JPEG to a directory "
"when a matching raw picture is found"
)
parser.add_argument(
"dir",
metavar="DIRECTORY",
type=str,
default=".",
nargs="?",
help="Directory containing the pictures",
)
parser.add_argument(
"-d",
"--dry",
action="store_true",
help="Do not actually rename, just show old and new path",
)
args = parser.parse_args()
main(args)

View file

@ -50,6 +50,7 @@ if __name__ == "__main__":
parser.add_argument("-f", "--from", env_var="FROM") parser.add_argument("-f", "--from", env_var="FROM")
parser.add_argument("-t", "--to", env_var="TO") parser.add_argument("-t", "--to", env_var="TO")
parser.add_argument("-T", "--reply-to", env_var="REPLYTO")
parser.add_argument( parser.add_argument(
"-j", "-j",
"--subject", "--subject",
@ -77,6 +78,8 @@ if __name__ == "__main__":
setattr(args, "from", args.sender) setattr(args, "from", args.sender)
if args.to is None: if args.to is None:
args.to = args.receiver[0] args.to = args.receiver[0]
if args.reply_to is None:
args.reply_to = args.to
if args.password: if args.password:
password = args.password password = args.password
args.password = "********" args.password = "********"
@ -98,6 +101,7 @@ XJS*C4JDBQADN1.NSBN3*2IDNEN*GTUBE-STANDARD-ANTI-UBE-TEST-EMAIL*C.34X"""
From: {args.me} <{getattr(args, 'from')}> From: {args.me} <{getattr(args, 'from')}>
Subject: {args.subject} Subject: {args.subject}
To: {args.to} To: {args.to}
Reply-To: {args.reply_to}
Message-ID: {mid} Message-ID: {mid}
Hello there, Hello there,