Skip to content

Commit

Permalink
📻️ added new poster themes #25
Browse files Browse the repository at this point in the history
- Increased poster resolution size
- Introduced new themes: Catppuccin, Gruvbox, Everforest, Nord, and Rosepine
- Updated consts.py
  • Loading branch information
TrueMyst committed Dec 31, 2024
1 parent 7a2ccb6 commit 5644f1a
Show file tree
Hide file tree
Showing 18 changed files with 144 additions and 66 deletions.
Binary file removed BeatPrints/assets/templates/banner_dark.png
Binary file not shown.
Binary file removed BeatPrints/assets/templates/banner_light.png
Binary file not shown.
Binary file added BeatPrints/assets/templates/catppuccin.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added BeatPrints/assets/templates/dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added BeatPrints/assets/templates/everforest.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added BeatPrints/assets/templates/gruvbox.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added BeatPrints/assets/templates/light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added BeatPrints/assets/templates/nord.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added BeatPrints/assets/templates/rosepine.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
82 changes: 56 additions & 26 deletions BeatPrints/consts.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,38 +9,68 @@
S = Size
C = Cords
P = Path
PL = Palette
CL = Color
"""

import os
from typing import Literal

MAX_ROWS = 5
MAX_WIDTH = 1020

S_TRACKS = 35
S_SPACING = 45
S_COVER = (1020, 1020)
S_SPOTIFY_CODE = (330, 85)
S_HEADING = 80
S_ARTIST = 60
S_DURATION = 45
S_LYRICS = 42
S_LABEL = 30

C_COVER = (60, 60)
C_HEADING = (60, 1275)
C_ARTIST = (60, 1350)
C_LYRICS = (60, 1395)
C_TRACKS = (60, 1390)
C_LABEL = (1080, 1615)

C_DURATION = (1080, 1275)
C_PALETTE = (60, 1120)
C_ACCENT = (0, 1720, 1140, 1740)
C_SPOTIFY_CODE = (45, 1610)

CL_FONT_DARK_MODE = (193, 189, 178)
CL_FONT_LIGHT_MODE = (50, 47, 48)
MAX_WIDTH = 2040

S_MAX_HEADING_WIDTH = 1760
S_TRACKS = 70
S_SPACING = 90
S_COVER = (2040, 2040)
S_SPOTIFY_CODE = (660, 170)
S_HEADING = 160
S_ARTIST = 120
S_DURATION = 90
S_LYRICS = 84
S_LABEL = 60

C_COVER = (120, 120)
C_HEADING = (120, 2550)
C_ARTIST = (120, 2700)
C_LYRICS = (120, 2790)
C_TRACKS = (120, 2780)
C_LABEL = (2160, 3230)
C_DURATION = (2160, 2550)
C_PALETTE = (120, 2240)
C_ACCENT = (0, 3440, 2280, 3480)
C_SPOTIFY_CODE = (90, 3220)

PL_BOX_WIDTH = 340
PL_BOX_HEIGHT = 2325

CL_FONT_DARK = (193, 189, 178)
CL_FONT_LIGHT = (50, 47, 48)
CL_FONT_CATPPUCCIN = (205, 214, 244)
CL_FONT_GRUVBOX = (221, 199, 161)
CL_FONT_NORD = (216, 222, 233)
CL_FONT_ROSEPINE = (224, 222, 244)
CL_FONT_EVERFOREST = (211, 198, 170)

THEMES = {
"Light": CL_FONT_LIGHT,
"Dark": CL_FONT_DARK,
"Catppuccin": CL_FONT_CATPPUCCIN,
"Gruvbox": CL_FONT_GRUVBOX,
"Nord": CL_FONT_NORD,
"RosePine": CL_FONT_ROSEPINE,
"Everforest": CL_FONT_EVERFOREST,
}

THEME_OPTS = Literal[
"Light",
"Dark",
"Catppuccin",
"Gruvbox",
"Nord",
"RosePine",
"Everforest",
]

CL_WHITE = (255, 255, 255, 255)
CL_TRANSPARENT = (0, 0, 0, 0)
Expand Down
13 changes: 13 additions & 0 deletions BeatPrints/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,16 @@ def __init__(
):
self.message = message
super().__init__(self.message)


class ThemeNotFound(Exception):
"""
Raised when the specified theme is not found or is invalid.
"""

def __init__(
self,
message="The specified theme could not be found. Please ensure the theme name is valid.",
):
self.message = message
super().__init__(self.message)
31 changes: 15 additions & 16 deletions BeatPrints/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,10 @@ def draw_palette(
# Draw each color in the palette as a box
for i in range(6):
x, y = C_PALETTE
start, end = 170 * i, 170 * (i + 1)
start, end = PL_BOX_WIDTH * i, PL_BOX_WIDTH * (i + 1)

# Draw the box for the current color
draw.rectangle(((x + start, y), (x + end, 1160)), fill=palette[i])
draw.rectangle(((x + start, y), (x + end, PL_BOX_HEIGHT)), fill=palette[i])

# If accent is True, draw the accent color at the bottom
if accent:
Expand Down Expand Up @@ -117,19 +117,22 @@ def magicify(image: Image.Image) -> Image.Image:
return contrast.enhance(0.8)


def scannable(id: str, darktheme: bool = False, is_album: bool = False) -> Image.Image:
def scannable(
id: str, theme: THEME_OPTS = "Light", is_album: bool = False
) -> Image.Image:
"""
Generates a Spotify scannable code for a track or album.
Args:
id (str): The Spotify track or album ID.
darktheme (bool): Whether to use dark theme. Defaults to False.
theme (str): The theme for the scannable code. Defaults to "Light".
is_album (bool): If True, generates for an album. Defaults to False.
Returns:
Image.Image: The resized scannable code image.
"""
color = CL_FONT_DARK_MODE if darktheme else CL_FONT_LIGHT_MODE

color = THEMES[theme]
item_type = "album" if is_album else "track"

# Construct the URL to fetch the scannable code from Spotify
Expand Down Expand Up @@ -186,22 +189,18 @@ def cover(image_url: str, image_path: Optional[str]) -> Image.Image:
return magicify(img.resize(S_COVER))


def get_theme(dark_theme: bool):
def get_theme(theme: THEME_OPTS = "Light") -> Tuple[tuple, str]:
"""
Returns theme-related properties based on the selected theme.
Args:
dark_theme (bool): Whether to use dark theme.
theme (str): The selected theme. Default is "Light".
Returns:
Tuple: The theme color and template path.
Tuple[tuple, str]: A tuple containing the theme color and the template path.
"""
# Return appropriate color and template based on theme
color, template = (
(CL_FONT_DARK_MODE, "banner_dark.png")
if dark_theme
else (CL_FONT_LIGHT_MODE, "banner_light.png")
)

template_path = os.path.join(P_TEMPLATES, template)

color = THEMES[theme]
template_path = os.path.join(P_TEMPLATES, f"{theme.lower()}.png")

return color, template_path
36 changes: 24 additions & 12 deletions BeatPrints/poster.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@
from pathlib import Path
from typing import Optional, Union


from PIL import Image, ImageDraw

from .consts import *
from . import image, write

from .consts import *
from .errors import ThemeNotFound
from .utils import filename, organize_tracks
from .spotify import TrackMetadata, AlbumMetadata

Expand Down Expand Up @@ -50,12 +51,14 @@ def _add_common_text(
write.heading(
draw,
C_HEADING,
875,
S_MAX_HEADING_WIDTH,
metadata.name.upper(),
color,
write.font("Bold"),
S_HEADING,
) # Add artist name
)

# Add artist name
write.text(
draw,
C_ARTIST,
Expand All @@ -81,7 +84,7 @@ def track(
metadata: TrackMetadata,
lyrics: str,
accent: bool = False,
dark_theme: bool = False,
theme: THEME_OPTS = "Light",
custom_cover: Optional[str] = None,
) -> None:
"""
Expand All @@ -91,15 +94,20 @@ def track(
metadata (TrackMetadata): Metadata containing details about the track.
lyrics (str): The lyrics of the track.
accent (bool, optional): Flag to add an accent at the bottom of the poster. Defaults to False.
dark_theme (bool, optional): Flag to use a dark theme. Defaults to False.
theme (str, optional): Specifies the theme to use. Must be one of "Light", "Dark", "Catppuccin", "Gruvbox", "Nord", "RosePine", or "Everforest". Defaults to "Light".
custom_cover (Optional[str], optional): Path to a custom cover image. Defaults to None.
"""

# Check if the theme mentioned is valid or not
if theme not in THEMES:
raise ThemeNotFound

# Get theme colors and template for the poster
color, template = image.get_theme(dark_theme)
color, template = image.get_theme(theme)

# Get cover art and spotify scannable code
cover = image.cover(metadata.image, custom_cover)
scannable = image.scannable(metadata.id, dark_theme)
scannable = image.scannable(metadata.id, theme)

with Image.open(template) as poster:
poster = poster.convert("RGB")
Expand Down Expand Up @@ -148,7 +156,7 @@ def album(
metadata: AlbumMetadata,
indexing: bool = False,
accent: bool = False,
dark_theme: bool = False,
theme: THEME_OPTS = "Light",
custom_cover: Optional[str] = None,
) -> None:
"""
Expand All @@ -158,16 +166,20 @@ def album(
metadata (AlbumMetadata): Metadata containing details about the album.
indexing (bool, optional): Flag to add index numbers to the tracks. Defaults to False.
accent (bool, optional): Flag to add an accent at the bottom of the poster. Defaults to False.
dark_theme (bool, optional): Flag to use a dark theme. Defaults to False.
theme (str, optional): Specifies the theme to use. Must be one of "Light", "Dark", "Catppuccin", "Gruvbox", "Nord", "RosePine", or "Everforest". Defaults to "Light".
custom_cover (Optional[str], optional): Path to a custom cover image. Defaults to None.
"""

# Check if the theme mentioned is valid or not
if theme not in THEMES:
raise ThemeNotFound

# Get theme colors and template for the poster
color, template = image.get_theme(dark_theme)
color, template = image.get_theme(theme)

# Get cover art and spotify scannable code
cover = image.cover(metadata.image, custom_cover)
scannable = image.scannable(metadata.id, dark_theme, is_album=True)
scannable = image.scannable(metadata.id, theme, is_album=True)

with Image.open(template) as poster:
poster = poster.convert("RGB")
Expand Down
13 changes: 10 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,25 @@

## 📦 Installation

You can install BeatPrints via `pip`:
You can install BeatPrints via:

```bash
# For pip users
pip install BeatPrints

# For poetry users
poetry add BeatPrints
```

Or, if you use Poetry:
Or if you prefer using just the CLI:

```bash
poetry add BeatPrints
pipx install BeatPrints
```

This will install the CLI, making it ready for you to use.
For more more infomation, check out [pipx](https://github.com/pypa/pipx)

## 🌱 Environment Variables

To get started with BeatPrints, you’ll need a `.env` file with these keys:
Expand Down
18 changes: 14 additions & 4 deletions cli/prompt.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import questionary

from rich import print
from BeatPrints import lyrics, spotify, poster, errors

from cli.conf import *
from cli import exutils, validate

from BeatPrints import lyrics, spotify, poster, errors

# Initialize components
ly = lyrics.Lyrics()
ps = poster.Poster(POSTERS_DIR)
Expand Down Expand Up @@ -134,8 +133,19 @@ def poster_features():
tuple: A tuple containing theme, accent, and image path options.
"""
features = questionary.form(
theme=questionary.confirm(
"💫 • Enable dark mode?", default=False, style=exutils.default
theme=questionary.select(
"💫 • Which theme do you prefer?",
choices=[
"Light",
"Dark",
"Catppuccin",
"Gruvbox",
"Nord",
"Rosepine",
"Everforest",
],
default="Light",
style=exutils.default,
),
accent=questionary.confirm(
"🌈 • Add a color accent?", default=False, style=exutils.default
Expand Down
2 changes: 1 addition & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
project = "BeatPrints"
copyright = "2024, elysianmyst"
author = "elysianmyst"
release = "v1.0.6"
release = "v1.1.0"

# -- General configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
Expand Down
13 changes: 10 additions & 3 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,24 @@ Homepage
📦 Installation
---------------

You can install BeatPrints via ``pip``:
You can install BeatPrints via:

.. code:: python
# For pip users
pip install BeatPrints
Or, if you use Poetry:
# For poetry users
poetry add BeatPrints
Or if you prefer using just the CLI:

.. code:: python
poetry add BeatPrints
pipx install BeatPrints
This will install the CLI, making it ready for you to use.
For more more infomation, check out `pipx <https://github.com/pypa/pipx>`_

🌱 Environment Variables
------------------------
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "BeatPrints"
version = "1.0.6"
version = "1.1.0"
description = "Create eye-catching, pinterest-style music posters effortlessly."
authors = ["elysianmyst <74355265+TrueMyst@users.noreply.github.com>"]
license = "CC-BY-NC-4.0"
Expand Down

0 comments on commit 5644f1a

Please sign in to comment.