mirror of
https://github.com/stronk-dev/Guitar-Sheet-Parser.git
synced 2025-07-05 08:25:09 +02:00
Added a simple arranger, which arranges the sections on pages
Output2Img now simply writes all of the sections on a page below each other
This commit is contained in:
parent
db9633a855
commit
0767b7c2eb
@ -36,7 +36,7 @@ def initConfig():
|
|||||||
'metaFontWeight': 8,
|
'metaFontWeight': 8,
|
||||||
'lyricfontfamily': 'fonts/CourierPrime-Regular.ttf',
|
'lyricfontfamily': 'fonts/CourierPrime-Regular.ttf',
|
||||||
'tablaturefontfamliy': 'fonts/CourierPrime-Bold.ttf',
|
'tablaturefontfamliy': 'fonts/CourierPrime-Bold.ttf',
|
||||||
'songFontWeight': 18,
|
'songFontWeight': 14,
|
||||||
'imageWidth': 595, 'imageHeight': 842, # A4 at 72dpi
|
'imageWidth': 595, 'imageHeight': 842, # A4 at 72dpi
|
||||||
'backgroundColour': '255,255,255',
|
'backgroundColour': '255,255,255',
|
||||||
'fontColour': '0,0,0',
|
'fontColour': '0,0,0',
|
||||||
|
@ -89,9 +89,6 @@ class Section:
|
|||||||
self.expectedHeight = -1
|
self.expectedHeight = -1
|
||||||
|
|
||||||
"""!@brief Calculates dimensions of rendered text
|
"""!@brief Calculates dimensions of rendered text
|
||||||
This function calculates the dimensions of each line of text
|
|
||||||
the section contains and sets the internal variables
|
|
||||||
@param section lib.dataStructures.Section object
|
|
||||||
@return None
|
@return None
|
||||||
"""
|
"""
|
||||||
def calculateSectionDimensions(self, fontTablature, fontLyrics):
|
def calculateSectionDimensions(self, fontTablature, fontLyrics):
|
||||||
@ -165,6 +162,13 @@ class Section:
|
|||||||
self.lyrics.append("")
|
self.lyrics.append("")
|
||||||
self.isParsed = True
|
self.isParsed = True
|
||||||
|
|
||||||
|
"""!@brief Class containing Sections which fit on 1 page
|
||||||
|
"""
|
||||||
|
class Page:
|
||||||
|
def __init__(self):
|
||||||
|
self.sections = []
|
||||||
|
self.totalHeight = -1
|
||||||
|
|
||||||
"""!@brief Class containing Song specific data
|
"""!@brief Class containing Song specific data
|
||||||
"""
|
"""
|
||||||
class Song:
|
class Song:
|
||||||
@ -179,8 +183,12 @@ class Song:
|
|||||||
self.sections = []
|
self.sections = []
|
||||||
# Meta info: the text before the first section
|
# Meta info: the text before the first section
|
||||||
self.metadata = ""
|
self.metadata = ""
|
||||||
|
self.metadataWidth = -1
|
||||||
|
self.metadataHeight = -1
|
||||||
# String of entire input
|
# String of entire input
|
||||||
self.rawData = ""
|
self.rawData = ""
|
||||||
|
# List of pages, which contain sections which fit on a page
|
||||||
|
self.pages = []
|
||||||
# Flag for succesfully parsed
|
# Flag for succesfully parsed
|
||||||
self.isParsed = False
|
self.isParsed = False
|
||||||
configObj = lib.config.config['output']
|
configObj = lib.config.config['output']
|
||||||
@ -197,21 +205,25 @@ class Song:
|
|||||||
self.fontTablature = ImageFont.truetype(configObj['tablaturefontfamliy'], self.fontSize)
|
self.fontTablature = ImageFont.truetype(configObj['tablaturefontfamliy'], self.fontSize)
|
||||||
self.configObj = configObj
|
self.configObj = configObj
|
||||||
|
|
||||||
"""!@brief Calculates the expected dimensions of all sections
|
|
||||||
|
"""!@brief Calculates dimensions of metadata
|
||||||
|
@param section lib.dataStructures.Section object
|
||||||
@return None
|
@return None
|
||||||
"""
|
"""
|
||||||
def prerenderSections(self):
|
def calculateMetadataDimensions(self):
|
||||||
for section in self.sections:
|
# metadata starts topMargin removed from top
|
||||||
section.calculateSectionDimensions(self.fontTablature, self.fontLyrics)
|
currentHeight = self.topMargin
|
||||||
|
maxWidth = 0
|
||||||
"""!@brief Checks whether we are overflowing on the width of the page
|
for line in self.metadata.split('\n'):
|
||||||
@return True if everything OK, False if overflowing
|
line = line.rstrip()
|
||||||
"""
|
if not line:
|
||||||
def checkOverflowX(self):
|
continue
|
||||||
for section in self.sections:
|
metadataTextWidth, metadataTextHeight = self.fontMetadata.getsize(line)
|
||||||
if section.expectedWidth > self.imageWidth:
|
if metadataTextWidth > maxWidth:
|
||||||
return False
|
maxWidth = metadataTextWidth
|
||||||
return True
|
currentHeight += metadataTextHeight
|
||||||
|
self.metadataWidth = maxWidth
|
||||||
|
self.metadataHeight = currentHeight
|
||||||
|
|
||||||
"""!@brief Resizes all sections by a specified amount
|
"""!@brief Resizes all sections by a specified amount
|
||||||
Also recalculates all section sizes afterwards
|
Also recalculates all section sizes afterwards
|
||||||
@ -224,6 +236,63 @@ class Song:
|
|||||||
self.fontTablature = ImageFont.truetype(self.configObj['tablaturefontfamliy'], self.fontSize)
|
self.fontTablature = ImageFont.truetype(self.configObj['tablaturefontfamliy'], self.fontSize)
|
||||||
self.prerenderSections()
|
self.prerenderSections()
|
||||||
|
|
||||||
|
"""!@brief Calculates the expected dimensions of all sections
|
||||||
|
@return None
|
||||||
|
"""
|
||||||
|
def prerenderSections(self):
|
||||||
|
self.calculateMetadataDimensions()
|
||||||
|
for section in self.sections:
|
||||||
|
section.calculateSectionDimensions(self.fontTablature, self.fontLyrics)
|
||||||
|
|
||||||
|
"""!@brief Calculates the expected dimensions of all sections
|
||||||
|
@return None
|
||||||
|
"""
|
||||||
|
def fitSectionsByWidth(self):
|
||||||
|
self.prerenderSections()
|
||||||
|
while not self.checkOverflowX():
|
||||||
|
#print("Overflowing on width of the page. Decreasing font size by 2...")
|
||||||
|
self.resizeAllSections(-2)
|
||||||
|
|
||||||
|
"""!@brief Checks whether we are overflowing on the width of the page
|
||||||
|
@return True if everything OK, False if overflowing
|
||||||
|
"""
|
||||||
|
def checkOverflowX(self):
|
||||||
|
for section in self.sections:
|
||||||
|
if section.expectedWidth > self.imageWidth:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
"""!@brief Fits current sections into pages
|
||||||
|
@return None
|
||||||
|
"""
|
||||||
|
def sectionsToPages(self):
|
||||||
|
self.prerenderSections()
|
||||||
|
# First page contains metadata
|
||||||
|
currentHeight = self.topMargin
|
||||||
|
currentHeight += self.metadataHeight
|
||||||
|
currentHeight += self.topMargin
|
||||||
|
curPage = Page()
|
||||||
|
# Now fit all sections
|
||||||
|
for section in self.sections:
|
||||||
|
if (section.expectedHeight == -1 or section.expectedWidth == -1):
|
||||||
|
print("Warning: this file was not processed correctly. The expected dimensions are not set")
|
||||||
|
# See if the section would fit on the current page - if it does not, we have a filled page
|
||||||
|
if currentHeight + section.expectedHeight > self.imageHeight:
|
||||||
|
curPage.totalHeight = currentHeight
|
||||||
|
self.pages.append(curPage)
|
||||||
|
currentHeight = self.topMargin
|
||||||
|
curPage = Page()
|
||||||
|
# Add setion header size and size of lines of data
|
||||||
|
headerWidth, headerHeight = self.fontTablature.getsize(section.header)
|
||||||
|
currentHeight += headerHeight
|
||||||
|
currentHeight += section.expectedHeight
|
||||||
|
curPage.sections.append(section)
|
||||||
|
# Margin between each section
|
||||||
|
currentHeight += self.topMargin
|
||||||
|
# No more sections left, so the current buffered image is ready to be written to file
|
||||||
|
curPage.totalHeight = currentHeight
|
||||||
|
self.pages.append(curPage)
|
||||||
|
|
||||||
"""!@brief Parses self.rawData into Section objects and metadata
|
"""!@brief Parses self.rawData into Section objects and metadata
|
||||||
@return None
|
@return None
|
||||||
"""
|
"""
|
||||||
|
14
main.py
14
main.py
@ -37,17 +37,17 @@ def main():
|
|||||||
print("Start parsing of file '{}'...".format(song.inputFile))
|
print("Start parsing of file '{}'...".format(song.inputFile))
|
||||||
# Initialise internal data structures
|
# Initialise internal data structures
|
||||||
song.initSections()
|
song.initSections()
|
||||||
# Prerender: calculate the expected dimensions for each section
|
# Fit all sections on each page, resizes down if it does not fit on width
|
||||||
song.prerenderSections()
|
song.fitSectionsByWidth()
|
||||||
# While we overflow on X: resize all sections down and recalculate
|
# Prerender: calculate Pages, and move sections into Pages
|
||||||
while not song.checkOverflowX():
|
song.sectionsToPages()
|
||||||
#print("Overflowing on width of the page. Decreasing font size by 2...")
|
# Optimalisation: check for whitespace, check verhouding of whitespace&first section on next page
|
||||||
song.resizeAllSections(-2)
|
# TODO
|
||||||
# Parse as PNG a4
|
# Parse as PNG a4
|
||||||
if song.isParsed:
|
if song.isParsed:
|
||||||
# Create subdirectory where we will output our images
|
# Create subdirectory where we will output our images
|
||||||
targetDirectory = song.outputLocation + "-a4-png"
|
targetDirectory = song.outputLocation + "-a4-png"
|
||||||
print("Successfully parsed file. Writing output to '{}'".format(song.inputFile, targetDirectory))
|
print("Successfully parsed file. Writing output to '{}'".format(targetDirectory))
|
||||||
# Write out metadata and sections, as many as can fit on one page
|
# Write out metadata and sections, as many as can fit on one page
|
||||||
output2img.outputToImage(targetDirectory, song)
|
output2img.outputToImage(targetDirectory, song)
|
||||||
|
|
||||||
|
@ -54,50 +54,44 @@ def outputToImage(folderLocation, songObj):
|
|||||||
currentHeight += metadataTextHeight
|
currentHeight += metadataTextHeight
|
||||||
# Margin between metadata and the first section
|
# Margin between metadata and the first section
|
||||||
currentHeight += songObj.topMargin
|
currentHeight += songObj.topMargin
|
||||||
# Iterate over each section
|
# Draw all pages
|
||||||
# NOTE: sections might be split into lists of pages containing a list of sections
|
for page in songObj.pages:
|
||||||
# This change will occur when we add an arranger which resizes sections to fit pages better
|
for section in page.sections:
|
||||||
for section in songObj.sections:
|
# Reset section specific variables
|
||||||
# Reset section specific variables
|
lineIterator = 0
|
||||||
lineIterator = 0
|
amountOfLines = len(section.lyrics)
|
||||||
amountOfLines = len(section.lyrics)
|
if (amountOfLines != len(section.tablatures)):
|
||||||
if (amountOfLines != len(section.tablatures)):
|
print("Cannot write this section to file, since it was not processed correctly. There are {} tablature lines and {} lyric lines. Aborting...".format(len(section.chords), amountOfLines))
|
||||||
print("Cannot write this section to file, since it was not processed correctly. There are {} tablature lines and {} lyric lines. Aborting...".format(len(section.chords), amountOfLines))
|
return
|
||||||
return
|
if (section.expectedHeight == -1 or section.expectedWidth == -1):
|
||||||
if (section.expectedHeight == -1 or section.expectedWidth == -1):
|
print("Cannot write this section to file, since it was not processed correctly. The expected dimensions are not set. Aborting...")
|
||||||
print("Cannot write this section to file, since it was not processed correctly. The expected dimensions are not set. Aborting...")
|
return
|
||||||
return
|
# write section title
|
||||||
# See if the section would fit on the current page - if it does not, write current buffered image & make the next image ready
|
headerWidth, headerHeight = songObj.fontTablature.getsize(section.header)
|
||||||
if currentHeight + section.expectedHeight > songObj.imageHeight:
|
draw.text((songObj.leftMargin,currentHeight), section.header, fill=songObj.fontColour, font=songObj.fontTablature)
|
||||||
#print("overflow! starting with a new image")
|
currentHeight += headerHeight
|
||||||
outputLocation = folderLocation + "/" + str(imageNumber) + ".png"
|
# Write each line tablature&lyric data
|
||||||
imageNumber += 1
|
while lineIterator < amountOfLines:
|
||||||
a4image.save(outputLocation)
|
#print("Printing tablatures line {} and lyrics line {}".format(section.tablatures[lineIterator], section.lyrics[lineIterator]))
|
||||||
currentHeight = songObj.topMargin
|
# Get tablatures&lyric line
|
||||||
a4image = Image.new('RGB',(songObj.imageWidth, songObj.imageHeight),(songObj.backgroundColour))
|
lyricTextWidth, lyricTextHeight = songObj.fontLyrics.getsize(section.lyrics[lineIterator])
|
||||||
draw = ImageDraw.Draw(a4image)
|
tablatureTextWidth, tablatureTextHeight = songObj.fontTablature.getsize(section.tablatures[lineIterator])
|
||||||
# write section title
|
# add to image file
|
||||||
headerWidth, headerHeight = songObj.fontTablature.getsize(section.header)
|
draw.text((songObj.leftMargin,currentHeight), section.tablatures[lineIterator], fill=songObj.fontColour, font=songObj.fontTablature)
|
||||||
draw.text((songObj.leftMargin,currentHeight), section.header, fill=songObj.fontColour, font=songObj.fontTablature)
|
currentHeight += tablatureTextHeight
|
||||||
currentHeight += headerHeight
|
draw.text((songObj.leftMargin,currentHeight), section.lyrics[lineIterator], fill=songObj.fontColour, font=songObj.fontLyrics)
|
||||||
# Write each line tablature&lyric data
|
currentHeight += lyricTextHeight
|
||||||
while lineIterator < amountOfLines:
|
lineIterator += 1
|
||||||
#print("Printing tablatures line {} and lyrics line {}".format(section.tablatures[lineIterator], section.lyrics[lineIterator]))
|
#print("currentheight={}".format(currentHeight))
|
||||||
# Get tablatures&lyric line
|
# Margin between each section
|
||||||
lyricTextWidth, lyricTextHeight = songObj.fontLyrics.getsize(section.lyrics[lineIterator])
|
currentHeight += songObj.topMargin
|
||||||
tablatureTextWidth, tablatureTextHeight = songObj.fontTablature.getsize(section.tablatures[lineIterator])
|
# Got all sections in the page, so write it
|
||||||
# add to image file
|
outputLocation = folderLocation + "/" + str(imageNumber) + ".png"
|
||||||
draw.text((songObj.leftMargin,currentHeight), section.tablatures[lineIterator], fill=songObj.fontColour, font=songObj.fontTablature)
|
a4image.save(outputLocation)
|
||||||
currentHeight += tablatureTextHeight
|
a4image = Image.new('RGB',(songObj.imageWidth, songObj.imageHeight),(songObj.backgroundColour))
|
||||||
draw.text((songObj.leftMargin,currentHeight), section.lyrics[lineIterator], fill=songObj.fontColour, font=songObj.fontLyrics)
|
draw = ImageDraw.Draw(a4image)
|
||||||
currentHeight += lyricTextHeight
|
currentHeight = songObj.topMargin
|
||||||
lineIterator += 1
|
imageNumber += 1
|
||||||
#print("currentheight={}".format(currentHeight))
|
|
||||||
# Margin between each section
|
|
||||||
currentHeight += songObj.topMargin
|
|
||||||
# No more sections left, so the current buffered image is ready to be written to file
|
|
||||||
outputLocation = folderLocation + "/" + str(imageNumber) + ".png"
|
|
||||||
a4image.save(outputLocation)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user