This article was originally written in August 2019 or so but never published after the 2019 Developer Students Clubs Open Hack Week. Was scrolling through old documents and stumbled upon it then felt the need to share it.
It still feels cool (and awesome) to say I wrote a desktop application in Python that allows for the mass manipulation of images π. Here's a bit of my journey, and an overview of the application π.
Some background
I'll be the first to admit that I'm probably not particularly good at designing UI & anything concerned with frontend and designs π. I'm not also an expert at making applications but I'm really good at finding solutions to problems π. What I do have is a really strong interest in programming.
How it all began
A hackathon was organized by Developer Students Clubs (DSC) UNILAG named Open Hack Week (OHW 2019) and all persons gathered were given about 12 problem statements out of which they were to form groups to attempt to solve the problem. My team attempted problem 8 which was a web crawler for research publications by lecturers in the school, we called it X-Crawler π. It was a platform that will be updated automatically with any new research publication from lecturers at the university. The hackathon was a week-long event starting Monday, ending on Saturday.
On the second/third day of the hackathon, about 4 more problem statements were presented out of which the task to build a certificate generator was part. This task was to build a program that will take in an image and CSV as input then return several images from the given source image with data inserted from the CSV file.
A CSV file is just a fancy term for a text file with commas and a lot of lines πππ. So, what the solution will do in layman terms is open the CSV file, copy its content line by line, then create a new picture from the source and put that extracted data inside it then go on till the CSV is empty. Pretty cool right? π well, it is not πΆ. The highest form of image manipulation I've ever done is edit pixel values, turn images to black and white with the pillow library and a little bit of computer vision, for this task I would need to be drawing images on images, even changing color and so on π¨. Aside from that, the program needed a way to track where to actually know where to insert the data from the CSV and the only way I can display any form of visualization to the user is with matplotlib, and it's kind of like a static drawing canvas. How the hell was I supposed to track mouse clicks and location. Deep down I knew I was in some serious shit π π.
I began coding anyway. Had Google and Stack overflow backing me up so I knew I could conquer any challenge that might want to pop up ππ€. First, I wrote a function that would read the data from the CSV and parse them into a list that can be iterated later. Next, I needed to learn how to draw text on images. After a little bit of googling, I stumbled upon Pillow library documentation, there was a particular section dedicated to drawing text. I said to myself "Na God save you oo" π. I added a new function to my script stolen gotten from the documentation which inserts the text into the given location. I added more functions to select the font and size of the text. "Local man was pleased π€ͺ"
The initial version of the app needed the placing positions defined in the code for it to know where to insert text. Well then I plotted the image data with matplotlib.implot, next was tracking mouse position. After another round of searching, I found a callback functionality in matplotlib documentation that allows a function to be called when certain events happen while the plot window was open and mouse clicks were one of this. I wrote a function that will store the mouse position in a list when called. This function contained code that will also plot a scatter plot on the image plot to let the user know where they clicked.
I did all this the same day I started and it was like I was finally done then Python bit me, the resulting images were being plotted wrongly π¨ππ. I don't know what happened but Python wasn't saving the real mouse values but something else, after hours of debugging I found out that Python was the one changing the x and y mouse points after I plotted my scatter plot, so I decided to save my mouse points before plotting that. I honestly don't know why it did that but I don't care, my code was working and that was all that mattered.
My initial version was working, I could track mouse points, generate desired images. And the work was done. I submitted that for OHW π. I knew a couple of things were not right for my app to be considered a "certificate generator" but I didn't really care. Pushing a stable version to GitHub was my main goal ππ. I would need to improve on my visualization so the user has a clear view of how the resulting image would look like, being able to enter different font size and color not just editing code before running, selecting texts that can be aligned to center, etc as well as many other things; I told myself I'll come to rewrite the program at a later time with all these features.
Moving on...
Some weeks after OHW, I picked up my code and decided to make it a full desktop app instead of a script you have to use your terminal to run. And so, I began.
I decided to use the Python EEL library for this (there's a high chance that the reader does not know this framework even if they code python, don't feel bad there was a time I didn't know it also and the next reader might not also know this LOL because itβs very new with a very small community). EEL allows the creation of web apps using python as the backend implementing bottle web framework which can then be shipped as desktop apps. It allows python and JavaScript to communicate using web sockets. If you've used Jupyter before, EEL allows you to create the kind of interface Jupyter uses where it sets up localhost in python then allows you to use the app in the browser π.
I already mentioned I wasn't good in UI so there's no way I was going to code one from scratch for this project, I instantly fired up mobirise which is a bootstrap landing page generator (more like a drag and drop WordPress that gives you your HTML codes). I made some elements with it then I edited the HTML codes to my specification later. Made a page for selecting image and CSV, another page where you'll edit your template, a loading page then a finished page (where you'll be told to share the app π). So now the app is going to be in 2 parts. A JavaScript app for the visualization and a Python part for the actual manipulation.
I thought everything was going to be a breeze till the codes started hitting me hard, I had problems right from the first page; I was using HTML for my UI and when you add a file with a form it only returns the name of the file and not the path located on the PC, this was a serious challenge because EEL did not support form POST requests. Well, I did something crazy here π€, I used the file selector functionality from Tkinter library to display the file selection box for the user when the path is gotten, it will be stored in a hidden input box on my page then the basename was shown in the HTML. The user will see this whole thing the same way as the HTML form file selector but deep down I know something else went on (#SCAM 101 π).
After getting the image and CSV file from the user, the values are passed to the second page where the image would need to be drawn on HTML5 canvas then the CSV columns displayed. I wrote the functions for reading the files in Python which will be called when the page loads in JavaScript. I've never used the canvas before so I just went on and coded the rest of the pages and the full functionality of the entire app. After a few days, the full app was ready, all that was left is returning those locations which was also the problem using matplotlib in version 1. Google, Stack overflow, et al, all came to the rescue and I was able to get the canvas able to display the image, track mouse clicks and location relative to the canvas in the page, also display sample texts and get variable font size and color working and ready to be passed to my generator function in Python. Some codes later and the whole project was completed πππ. Before this project I've always hated JavaScript, after working on this drawing functionality with it, I want to say that I hate JavaScript even more π€¬. I chose not to use any library or framework so as to keep the app light so all I did had to be implemented in Vanilla JavaScript. Also, JavaScript just started behaving stupidly over reasons it was not meant to. That's how I'll finish applying all my changes to a text element and once I create a new element all my previous changes will be deleted and I'm left with default values. As if that was not all, It got to a time my editor page was not being initialized by JavaScript so what I did was allow python first initialize the page then JS initializes it following that, you might say they are dependent on each other but trust me the values of the first have no effect on the second. JavaScript just decided to be stupid π‘.
Conclusion
Well, this was a bird's eye view of my journey, as well as the application itself. I have a lot more to tell but I'm lazy to do so (I didnβt even mention my GIF scam π or how I tackled my Python /r issue π€, or how I got my app working for all OSβs). And you're not getting the full list because I'm lazy to write it (took me about 9 months just to publish this).
The project was a really fun & interesting one from the first day, I learned a lot not only limited to using HTML5 Canvas but also Python EEL framework and I still want to work on more interesting projects; Mhen I sure love coding even with all the frustration attached π. Who would have thought I could have been able to pull that Tkinter stunt or even creating a whole drawing app with Vanilla JavaScript alone π³ and I hope it was an interesting read too.
Links
The project on GitHub - github.com/DSC-Unilag/Certificate-Generator
My GitHub - github.com/LordGhostX
My Twitter - twitter.com/LordGhostX