quotespy: Create graphics for quotes, lyrics, and tweets
In October 2019 I wrote a Medium article on how to create tweet-like graphics using Python and the PIL library. Well, now I’ve released a complete Python library that can be used for that purpose, but also for lyrics and quotes graphics. I called it quotespy.
In this article, I will show you demos based on the examples included in the project’s README, ranging from the most simple usage to a more “advanced” case which integrates quotespy with the os
module.
For starters, install the library with the usual pip command
pip install quotespy
And you’ll be good to go.
Creating lyrics/quotes graphics with quotespy.graphics
quotespy comes with two packages, one for tweet-like graphics and another for lyrics/quotes. We’ll go through the latter first.
As you can see, given only a dictionary with the graphic’s information and a graphic settings (default) format, the above script generates the following .png file.
Personally, I don’t think the font (Arial) for the default settings is that good for graphics/lyrics, but I chose it because (1) it’s the font for the tweets package and (2) it’s more commonly available out-of-the-box in possible users’ machines.
Hence, and to improve customization, instead of passing an empty dictionary as the second argument, you can pass your own settings. I call this the graphic_settings
dictionary and it includes formatting settings for the graphic. Please take into account that all dictionaries shown here, be it for the graphic’s information or graphical formatting, always require all the key-value pairs included in the examples. Speaking of that, please note that either an empty dictionary or a complete dictionary of custom settings must always be passed as the second positional argument.
As you can see in the snippet above, you can choose the font family, the font size, the dimensions of the graphic (width and height, both in pixels), the color scheme (background and text color, both as Hexadecimal values), the maximum number of characters to have per line, and the vertical margin to leave between lines. Oh, and since we are using custom graphic settings, there’s no need to specify the default_settings_format
.
Furthemore, note that the output directory was also specified in this case. When omitted, the created graphic’s destination defaults to the current directory, but when a path is given (either relative or absolute), it is saved in that location. In this instance, the graphic is saved in the “output” folder found in the current directory.
Ideally, a graphic created with the default settings would look like this, using the Inkfree font, but since it is not available by default, I kept Arial for the default settings.
Next up is an example for loading multiples lyrics/quotes from a .txt or .json file to create a graphic for each one. Assuming you have a .json file like this at hand
Or a .txt alternative
You can use the gen_graphics
function to load the file and create a graphic for each quote/lyrics:
Again, we go with custom graphic settings, and specify a relative path to the .json file of quotes. All quote graphics created are saved in the “output” folder once more. Here is an example of one of the created quote graphics.
Of course, the same gen_graphics
function could be used for a lyrics file. The variable factor here is the graphic settings used, the text is simply what is drawn in the graphic.
And that’s pretty much it for the graphics
package. Now let’s move on to the tweet_graphics
counterpart.
Creating tweet graphics with quotespy.tweet_graphics
Creating tweet graphics is equally simple, with just some added key-value pairs for the information and graphic settings dictionaries.
For starters, the tweet_info
dictionary requires the name of the tweet/file (instead of title
), the username and tag/handle of the user and, of course, the actual tweet’s text. The path to a profile picture can also be added or, alternatively, left as an empty string.
In this case, the profile picture is available in a “samples” folder, under the name “user_photo.png”, that is, it’s location is specified with a relative path. Oh, and please note that the profile picture is resized to a tenth of the graphic’s dimensions, with a circular crop.
Akin to the graphics
package, the create_tweet
function also accepts default graphic settings: “blue”, “light” and “dark”, which mirror Twitter’s themes. Below is the output graphic of the code snippet shown.
And, of course, it is possible to pass custom graphic settings.
Note how the graphic_settings
dictionary for tweets includes font_size_text
and font_size_header
keys, so the header (username and tag/handle) can be of a different size from the rest of the tweet.
This time the graphic is saved in the current directory, and it doesn’t have a profile picture:
Finally, it is also possible to load a file with multiple tweets, but this time only .json files.
Assuming you have a file like this (an array of JSON objects which are loaded as a list of graphic_info
dictionaries):
It is then possible to generate graphics for each tweet in the file with this code:
Which creates two graphics, one for each tweet in the file, using the default “light” theme graphic settings. The second one looks like this:
I’m showing the second tweet graphic so you can see how the graphics look like for a long username and text.
“Advanced usage”
Lastly, I’d like to show an “advanced usage” example which integrates quotespy with the os
module to create both “light” and “dark” mode graphics of tweets, in a folder for each tweet.
Firstly, there is a list of tweet_info
dictionaries, that is, a list of tweets. The “top-level” save destination is the “output” folder once again, specified in the PATH
variable. Afterwards, two custom graphic settings dictionaries are specified: one for the light mode and another for the dark mode.
Now that all the information is settled down, we can loop through the list of tweets to create each one with the create_tweet
function. However, before creating any graphic we create a new folder in “output” to store both versions (light and dark) of the current tweet. This is achieved by creating a folder of the same name as the tweet through os.path.join
and the mkdir
terminal command (executed through os.system
).
Finally, the light mode version is created and, to create the dark counterpart, “_DM” is appended to the tweet’s name in order to have a different name for each version. If the name was the same, the dark mode version would overwrite the light mode version.
After running the script, the “output” folder now contains three folders, one for each tweet, with a dark and light version in each.
Conclusion
Writing this library was a valuable experience. First and foremost, I believe I created an interesting library that can help people get content ready to post on social media. Second, I learned a lot creating it. I have been doing these creations with independent scripts locally, but now the code is publicly available for usage.
Another great thing from this project was getting acquainted with the pytest
testing library. It’s flexible and allows for fast writing of automated tests, with small overhead for writing variations of the same test (for instance, testing which exception a function throws for different graphic_settings
dictionaries). Unfortunately I didn’t get to write all the tests I wanted to, but at least the library has a good enough code coverage (around 80%).
Lastly, I’d like to point in the direction of the “Python project maturity checklist”, by Michał Karzyński. It truly was a great guide to go from detached script to a finalized library ready to be published.