Merge branch 'master' of bitbucket.org:MoonQ/mirva

This commit is contained in:
ville rantanen
2021-09-20 10:41:19 +03:00
4 changed files with 104 additions and 19 deletions

View File

@@ -1,6 +1,7 @@
# Mirva # Mirva
A tool to create a web gallery from a single folder of images. A tool to create a web gallery from a single folder of images.
Also .mp4 files are included in the gallery
## Installation ## Installation

View File

@@ -1,4 +1,4 @@
__version__ = "20210821.0" __version__ = "20210831.0"
def get_version(): def get_version():

View File

@@ -16,6 +16,9 @@ class Mirva:
) )
self.resource_dir = ".mirva" self.resource_dir = ".mirva"
self.config_file = os.path.join(self.resource_dir, "config.cfg") self.config_file = os.path.join(self.resource_dir, "config.cfg")
self.config_backup = os.path.join(self.resource_dir, "config.cfg.bkp")
self.image_match = re.compile(".*\.jpg$|.*\.jpeg$|.*\.png$|.*\.gif$|.*\.tif$", re.I)
self.video_match = re.compile(".*\.mp4$", re.I)
self.get_options() self.get_options()
os.chdir(self.options.folder) os.chdir(self.options.folder)
self.write_resources() self.write_resources()
@@ -24,8 +27,9 @@ class Mirva:
self.create_config() self.create_config()
print("Config created: Exiting without gallery creation. Check config first.") print("Config created: Exiting without gallery creation. Check config first.")
return return
self.create_config()
self.get_config() self.get_config()
if self.options.exif:
self.append_exif()
self.create_posts() self.create_posts()
self.write_index() self.write_index()
self.write_mediums() self.write_mediums()
@@ -33,11 +37,11 @@ class Mirva:
def create_config(self): def create_config(self):
config = configparser.ConfigParser() self.config = configparser.ConfigParser()
config.read(self.config_file) self.config.read(self.config_file)
config_changed = False config_changed = False
if not "SITE" in config: if not "SITE" in self.config:
config["SITE"] = { self.config["SITE"] = {
"title": "", "title": "",
"sub_title": "", "sub_title": "",
"intro": "", "intro": "",
@@ -46,20 +50,14 @@ class Mirva:
config_changed = True config_changed = True
for f in self.file_list: for f in self.file_list:
if not f in config: if not f in self.config:
title, _ = os.path.splitext(f) title, _ = os.path.splitext(f)
title = title.replace("_", " ") title = title.replace("_", " ")
config[f] = {"title": title, "description": ""} self.config[f] = {"title": title, "description": ""}
config_changed = True config_changed = True
if config_changed: if config_changed:
print( self.write_config()
"Modified config: {}".format(
os.path.join(self.options.folder, self.config_file)
)
)
with open(self.config_file, "wt") as fp:
config.write(fp)
def create_posts(self): def create_posts(self):
@@ -75,13 +73,28 @@ class Mirva:
self.config = configparser.ConfigParser() self.config = configparser.ConfigParser()
self.config.read(self.config_file) self.config.read(self.config_file)
def write_config(self):
print(
"Modified config: {}".format(
os.path.join(self.options.folder, self.config_file)
)
)
if os.path.exists(self.config_file):
with open(self.config_file, "rt") as reader:
with open(self.config_backup, "wt") as writer:
writer.write(reader.read())
with open(self.config_file, "wt") as fp:
self.config.write(fp)
def get_files(self): def get_files(self):
image_match = re.compile(".*\.jpg$|.*\.jpeg$|.*\.png$|.*\.gif$|.*\.tif$", re.I) image_match = re.compile(".*\.jpg$|.*\.jpeg$|.*\.png$|.*\.gif$|.*\.tif$", re.I)
files = [] files = []
for f in sorted(os.listdir(".")): for f in sorted(os.listdir(".")):
if f.startswith("."): if f.startswith("."):
continue continue
if not image_match.match(f): if not (self.image_match.match(f) or self.video_match.match(f)):
continue continue
files.append(f) files.append(f)
return files return files
@@ -95,7 +108,7 @@ class Mirva:
) )
# parser.add_argument("-v", default=False, action="store_true") # parser.add_argument("-v", default=False, action="store_true")
parser.add_argument( parser.add_argument(
"--config", default=False, action="store_true", help="Write config and exit" "--config", default=False, action="store_true", help="Write config and exit. Required if more images are added."
) )
parser.add_argument( parser.add_argument(
"--force", "--force",
@@ -103,6 +116,12 @@ class Mirva:
action="store_true", action="store_true",
help="Force regeneration of middle sized images", help="Force regeneration of middle sized images",
) )
parser.add_argument(
"--exif",
default=False,
action="store_true",
help="Append EXIF information to image descriptions",
)
parser.add_argument( parser.add_argument(
"--version", "--version",
action="version", action="version",
@@ -218,6 +237,22 @@ function create_button(direction, to) {{
def get_post(self, image, title, content): def get_post(self, image, title, content):
if self.video_match.match(image):
return """
<div class="post">
<div class="navigation">&nbsp;</div>
<div class=center><a href="{image}">
<video class=post_image controls >
<source src="{image}" type="video/mp4" >
</video>
</a></div>
<div class="meta"><div class="name">{title}</div></div>
<div style="clear: both;">&nbsp;</div>
<div class="entry">{content}</div>
</div>""".format(
image=image, title=title, content=content
)
return """ return """
<div class="post"> <div class="post">
<div class="navigation">&nbsp;</div> <div class="navigation">&nbsp;</div>
@@ -287,9 +322,11 @@ function create_button(direction, to) {{
if link: if link:
r = 0 r = 0
res = "{:d}x{:d}>".format(int(r), int(r))
force = self.options.force force = self.options.force
for f in self.file_list: for f in self.file_list:
res = "{:d}x{:d}>".format(int(r), int(r)) if self.video_match.match(f):
continue
outfile = os.path.join(".med", "{}.jpg".format(f)) outfile = os.path.join(".med", "{}.jpg".format(f))
if force: if force:
try: try:
@@ -319,4 +356,49 @@ function create_button(direction, to) {{
] ]
sys.stdout.write(".") sys.stdout.write(".")
sys.stdout.flush() sys.stdout.flush()
subprocess.call(convargs) subprocess.run(convargs)
sys.stdout.write("\n")
def append_exif(self):
exif_format = '''
<ul>
<li>Date: %[EXIF:DateTimeOriginal]
<li>Camera: %[EXIF:Make] %[EXIF:Model]
<li>Parameters: %[EXIF:ExposureTime]s / F%[EXIF:FNumber] / Focal %[EXIF:FocalLength]
<li>Size: %w x %h / {size}
</ul>
'''
for f in self.config:
if f in self.file_list:
sys.stdout.write(".")
sys.stdout.flush()
file_size = human_size(f)
p = subprocess.run(
['identify','-format',exif_format.format(size=file_size),"{}[0]".format(f)],
capture_output = True
)
self.config[f]['description'] += p.stdout.decode('utf-8')
sys.stdout.write("\n")
self.write_config()
def human_size(file_name, precision=1):
size = os.path.getsize(file_name)
if size == None:
return "nan"
sign = ""
if size < 0:
sign = "-"
size = -size
suffixes = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB"]
suffixIndex = 0
defPrecision = 0
while size > 1024:
suffixIndex += 1
size = size / 1024.0
defPrecision = precision
return "%s%.*f%s" % (sign, defPrecision, size, suffixes[suffixIndex])

View File

@@ -203,11 +203,13 @@ a:hover {
.post_image { .post_image {
max-height: calc(100vh - 60px); max-height: calc(100vh - 60px);
max-width: calc(100vw - 128px); max-width: calc(100vw - 128px);
display: inline;
} }
@media only screen and (max-width: 800px) { @media only screen and (max-width: 800px) {
.post_image { .post_image {
max-height: calc(100vh - 2px); max-height: calc(100vh - 2px);
max-width: calc(100vw - 2px); max-width: calc(100vw - 2px);
display: inline;
} }
} }
/* Footer */ /* Footer */