Pārlūkot izejas kodu

update readme + fix bug w/ structure regex + fix bug slide misordering bug + slight code restructuring

Noah Vogt 2 gadi atpakaļ
vecāks
revīzija
e63a857161
3 mainītis faili ar 103 papildinājumiem un 34 dzēšanām
  1. 53 4
      README.md
  2. BIN
      media/start-slide-example.jpg
  3. 50 30
      slidegen.py

+ 53 - 4
README.md

@@ -47,7 +47,7 @@ As the top of the file are these five metadata entries. We call them *metadata s
 
 As for the syntax, each line starts with the metadata string, followed by *": "*, and ends with a non-empty string that acts as the value of the metadata string, which we call *metadata value*.  The `structure` is allowed only `R` and non-negative integers values separated by one comma each, which represents the structure or order in which to song is to be played by dividing the song into refrain and verses. The values in between the commas are called *structure elements*.
 
-Hence to check if a line in the header has the correct syntax use the following regular expression: `^(?!structure)\S+: .+|^structure: ([0-9]+|R)(,([0-9]+|R))+$`. What is not captured syntactically by this regex is that each metadata string and value pair must appear *exactly once* in the header.
+Hence to check if a line in the header has the correct syntax use the following regular expression: `^(?!structure)\S+: .+|^structure: ([0-9]+|R)(,([0-9]+|R))*$`. What is not captured syntactically by this regex is that each metadata string and value pair must appear *exactly once* in the header.
 
 The semantics of the other metadata values can be pretty much whatever you want, as long as they adhere to the syntax. Note also that the arrangement of lines doesn't have to match the list above, e.g. the line with the book metadata string can be above the line containing the title metadata, but note that it is probably better to not mix this up anyway for quicker manual editing's sake.
 
@@ -85,12 +85,60 @@ Here is a example of a text body using the first three verses of *'Amazing Grace
 
 ### Configuration
 
-The configuration of *slidegen* is handled via constants in `*.py` files. The default configuration is stored in `config/default_config.py`, and in the same form a custom user-defined configuration can optionally be placed in `config/config.py`. You don't have to specify all the constants present in the default config, only the one's you want to change.
+The configuration of `slidegen.py` is handled via constants in `*.py` files. The default configuration is stored in `config/default_config.py`, and in the same form a custom user-defined configuration can optionally be placed in `config/config.py`. You don't have to specify all the constants present in the default config, only the one's you want to change.
 
 For example, if you want to change the text color to green and the file extension the jpeg, your `config/config.py` could look like this:
 
-    TEXT_COLOR = "green"
-    FILE_EXTENSION = "jpeg"
+```python
+TEXT_COLOR = "green"
+FILE_EXTENSION = "jpeg"
+```
+
+Now for explanation of the individual entries.
+
+#### File Format and Naming
+
+`IMAGE_FORMAT` forces a specific file format when writing the files in formats accepted by ImageMagick. The individual slides get named in this form: `${IMAGE_FORMAT}${SLIDE_NUMBER}${FILE_EXTENSION}`. Hence with the default config of
+
+```python
+IMAGE_FORMAT = "jpeg"
+FILE_EXTENSION = "jpg"
+FILE_NAMEING = "slide"
+```
+
+the slides would be named `slide1.jpg`, `slide2.jpg`, `slide3.jpg` etc.
+
+#### Dimensions
+
+`WIDTH` and `HEIGHT` present the output resolution of the slide in pixels. Meaning for 4K slides you would have to use
+
+```python
+WIDTH = 3840
+HEIGHT = 2160
+```
+
+#### General Colors
+
+Now let us look at the start slide. With `BG_COLOR` we can set the background for all slides and `FG_COLOR` sets the color of the what we call *titlebar*. Note the color values are again in the typical form accepted by ImageMagick.
+
+```python
+BG_COLOR = "white"
+FG_COLOR = "#6298a4"
+```
+
+![example: start slide](media/start-slide-example.jpg)
+
+#### Titlebar
+
+```python
+TITLE_COLOR = "#d8d5c4"
+MAX_TITLE_FONT_SIZE = 70
+MIN_TITLE_FONT_SIZE = 20
+TITLE_FONT_SIZE_STEP = 10
+TITLE_HEIGHT = 160
+TITLEBAR_Y = 65
+```
+
 
 ## Roadmap
 
@@ -108,6 +156,7 @@ These are some issues and possible changes that will be addressed or at least co
 - use a more typical commandline argument system
 - add more documentation, especially explaining the slide generation and its configuration
 - better handling of font path Configuration
+- add tests
 
 ## Licensing
 

BIN
media/start-slide-example.jpg


+ 50 - 30
slidegen.py

@@ -24,6 +24,7 @@ import sys
 import colorama
 
 from wand.exceptions import BlobError
+from wand.image import Image
 
 from utils import (
     log,
@@ -59,34 +60,7 @@ class Slidegen:
         self.calculate_desired_structures()
         self.generate_slides()
 
-    def generate_slides(self) -> None:
-        song_template = self.song_template_form()
-        log("generating template...")
-        template_img = song_template.get_template(self.metadata["title"])
-
-        first_slide = self.start_slide_form()
-        log("generating start slide...")
-        start_slide_img = first_slide.get_slide(
-            template_img,
-            self.metadata["book"],
-            self.metadata["text"],
-            self.metadata["melody"],
-        )
-        start_slide_img.format = const.IMAGE_FORMAT
-        try:
-            start_slide_img.save(
-                filename=path.join(
-                    self.output_dir,
-                    const.FILE_NAMEING + "1." + const.FILE_EXTENSION,
-                )
-            )
-        except BlobError:
-            error_msg("could not write start slide to target directory")
-
-        log("generating song slides...")
-        # unique_structures: list = list(set(self.chosen_structure))
-
-        # count number of slides to be generated
+    def count_number_of_slides_to_be_generated(self) -> int:
         slide_count: int = 0
         for structure in self.chosen_structure:
             line_count: int = len(self.songtext[structure].splitlines())
@@ -97,6 +71,28 @@ class Slidegen:
             else:
                 slide_count += 1
 
+        return slide_count
+
+    def generate_slides(self) -> None:
+        template_img: Image = self.generate_song_template()
+
+        slide_count: int = self.count_number_of_slides_to_be_generated()
+        zfill_length: int = len(str(slide_count))
+
+        self.generate_start_slide(template_img, zfill_length)
+        self.generate_song_slides(slide_count, template_img, zfill_length)
+
+    def generate_song_template(self) -> Image:
+        song_template = self.song_template_form()
+        log("generating template...")
+        return song_template.get_template(self.metadata["title"])
+
+    def generate_song_slides(
+        self, slide_count, template_img, zfill_length
+    ) -> None:
+        log("generating song slides...")
+        # unique_structures: list = list(set(self.chosen_structure))
+
         current_slide_index: int = 0
 
         for index, structure in enumerate(self.chosen_structure):
@@ -168,7 +164,7 @@ class Slidegen:
                         filename=path.join(
                             self.output_dir,
                             const.FILE_NAMEING
-                            + str(current_slide_index + 1)
+                            + str(current_slide_index + 1).zfill(zfill_length)
                             + "."
                             + const.FILE_EXTENSION,
                         )
@@ -176,6 +172,30 @@ class Slidegen:
                 except BlobError:
                     error_msg("could not write slide to target directory")
 
+    def generate_start_slide(self, template_img, zfill_length) -> None:
+        log("generating start slide...")
+
+        first_slide = self.start_slide_form()
+        start_slide_img = first_slide.get_slide(
+            template_img,
+            self.metadata["book"],
+            self.metadata["text"],
+            self.metadata["melody"],
+        )
+        start_slide_img.format = const.IMAGE_FORMAT
+        try:
+            start_slide_img.save(
+                filename=path.join(
+                    self.output_dir,
+                    const.FILE_NAMEING
+                    + "1".zfill(zfill_length)
+                    + "."
+                    + const.FILE_EXTENSION,
+                )
+            )
+        except BlobError:
+            error_msg("could not write start slide to target directory")
+
     def parse_file(self) -> None:
         self.parse_metadata()
         self.parse_songtext()
@@ -198,7 +218,7 @@ class Slidegen:
                 content = content[line_nr:]
                 break
             if not re.match(
-                r"^(?!structure)\S+: .+|^structure: ([0-9]+|R)(,([0-9]+|R))+$",
+                r"^(?!structure)\S+: .+|^structure: ([0-9]+|R)(,([0-9]+|R))*$",
                 line,
             ):
                 if line[-1] == "\n":