diff --git a/src/generate_images.py b/src/generate_images.py index e18829f..e9c87f6 100644 --- a/src/generate_images.py +++ b/src/generate_images.py @@ -1,86 +1,25 @@ -from xml.etree import ElementTree import subprocess import tempfile -import zipfile -import shutil import sys import os from PIL import Image, ImageOps -from modules import logger +from modules import logger, mscz RATIO = 16/9 # 16:9 -def get_elements(root, attribute): - return [i for i in root if i.tag == attribute] - -def get_element(root, attribute): - elems = get_elements(root, attribute) - - if len(elems) > 1: - print(f"More than one '{attribute}' found", file=sys.stderr) - if len(elems) == 0: - raise IndexError(f"No '{attribute}' found !") - - return elems[0] - -def create_pagebreaks(data): - """ - Replaces all manual linebreaks by pagebreaks in a .mscx file (xml) - """ - root = ElementTree.fromstring(data) - - score = get_element(root, "Score") - parts = get_elements(score, "Part") - staffs = get_elements(score, "Staff") - for part in parts: - staffs += get_elements(part, "Staff") - - changes = 0 - for staff in staffs: - measures = get_elements(staff, "Measure") - for measure in measures: - layoutbreaks = get_elements(measure, "LayoutBreak") - for layoutbreak in layoutbreaks: - subtype = get_element(layoutbreak, "subtype") - if subtype.text == "line": - subtype.text = "page" - changes += 1 - - - return ElementTree.tostring(root), changes - -def remove_footer(data): - """ - Disable page footer in .mss (xml) - """ - root = ElementTree.fromstring(data) - - style = get_element(root, "Style") - show_footer = get_element(style, "showFooter") - show_footer.text = 0 - - return ElementTree.tostring(root) - -def prepare_mscz(source, dest): - shutil.copy(source, dest) - with zipfile.ZipFile(source) as inzip, zipfile.ZipFile(dest, "w") as outzip: - for inzipinfo in inzip.infolist(): - with inzip.open(inzipinfo) as infile: - if inzipinfo.filename.endswith(".mscx"): - new_data, changes = create_pagebreaks(infile.read()) - outzip.writestr(inzipinfo.filename, new_data) - elif inzipinfo.filename.endswith(".mss"): - new_data = remove_footer(infile.read()) - outzip.writestr(inzipinfo.filename, new_data) - else: - outzip.writestr(inzipinfo.filename, infile.read()) - def generate_images(mscz_file, base_dest): with tempfile.TemporaryDirectory() as tmpdirname: tmp_mscz = os.path.join(tmpdirname, "score.mscz") - prepare_mscz(mscz_file, tmp_mscz) + mscz.apply( + mscz_file, + tmp_mscz, + [ + mscz.patches.create_pagebreaks, + mscz.patches.remove_footer + ] + ) logger.log(".mscz file patched") subprocess.call(["mscore", tmp_mscz, "-o", base_dest+".png"]) diff --git a/src/images_to_video.sh b/src/images_to_video.sh deleted file mode 100755 index b2f40c3..0000000 --- a/src/images_to_video.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash - -IN=$1 -[[ $IN ]]|| IN="concat.txt" -FILES=$(cat $IN | grep file | awk '{print $2}' | uniq) - -echo $FILES - -# Get the larger width and height of all the images -WIDTH=$(identify -format "%w\n" $FILES | sort -nr | head -1) -HEIGHT=$(identify -format "%h\n" $FILES | sort -nr | head -1) - -echo $WIDTH x $HEIGHT - -# Center all the images and pad them to the larger width and height -# Set the border color to the dominant color of the image -for f in $FILES; do - BORDER_COLOR=$(magick $f -format "%[pixel:p{0,0}]" info:) - #BORDER_COLOR="srgb(255,255,255)" - echo "Border color: $BORDER_COLOR" - magick $f -gravity center -background none -extent ${WIDTH}x${HEIGHT} -bordercolor $BORDER_COLOR -border 0x0 $f -done \ No newline at end of file diff --git a/src/modules/mscz.py b/src/modules/mscz.py new file mode 100644 index 0000000..8f4dcb1 --- /dev/null +++ b/src/modules/mscz.py @@ -0,0 +1,111 @@ +from xml.etree import ElementTree +import functools +import zipfile +import shutil + + +""" +Patches +""" +class Patches: + def __init__(self): + self._data = {} + def __getattr__(self, key): + return self._data[key] + + +patches = Patches() + +def register_patch(file_ext): + def inner_wrapper(view): + patches._data[view.__name__] = (view, file_ext) + + @functools.wraps(view) + def wrapped_view(**kwargs): + return view(**kwargs) + + return wrapped_view + return inner_wrapper + + +@register_patch("mscx") +def create_pagebreaks(data): + """ + Replaces all manual linebreaks by pagebreaks in a .mscx file (xml) + """ + root = ElementTree.fromstring(data) + + score = get_element(root, "Score") + parts = get_elements(score, "Part") + staffs = get_elements(score, "Staff") + for part in parts: + staffs += get_elements(part, "Staff") + + for staff in staffs: + measures = get_elements(staff, "Measure") + for measure in measures: + layoutbreaks = get_elements(measure, "LayoutBreak") + for layoutbreak in layoutbreaks: + subtype = get_element(layoutbreak, "subtype") + if subtype.text == "line": + subtype.text = "page" + + + return ElementTree.tostring(root) + +@register_patch("mss") +def remove_footer(data): + """ + Disable page footer in .mss (xml) + """ + root = ElementTree.fromstring(data) + + style = get_element(root, "Style") + show_footer = get_element(style, "showFooter") + show_footer.text = 0 + + return ElementTree.tostring(root) + + +""" +The "main" apply function +""" +def get_elements(root, attribute): + return [i for i in root if i.tag == attribute] + +def get_element(root, attribute): + elems = get_elements(root, attribute) + + if len(elems) > 1: + print(f"More than one '{attribute}' found", file=sys.stderr) + if len(elems) == 0: + raise IndexError(f"No '{attribute}' found !") + + return elems[0] + +def apply(source, dest, patches): + """ + Apply functions to patch files inside a mscz + - source : source file + - dest : destination file, must differ + - patches : list of (function, file extension) + """ + patches_by_ext = {} + for func, ext in patches: + if ext not in patches_by_ext: + patches_by_ext[ext] = [] + + patches_by_ext[ext].append(func) + + shutil.copy(source, dest) + with zipfile.ZipFile(source) as inzip, zipfile.ZipFile(dest, "w") as outzip: + for inzipinfo in inzip.infolist(): + with inzip.open(inzipinfo) as infile: + ext = inzipinfo.filename.split(".")[-1] + if ext in patches_by_ext: + data = infile.read() + for func in patches_by_ext[ext]: + data = func(data) + outzip.writestr(inzipinfo.filename, data) + else: + outzip.writestr(inzipinfo.filename, infile.read()) \ No newline at end of file