A cool use for AWS Lambdas extremely simple to set up service.

About two years ago when in a Discord chat with my friends, one of them posted a link to an ascii art image of Mario (the infamous video game character and not some unknown Italian man) and it made me curious as to how this would be implemented with code. So naturally I looked up “Ascii art ‘insert whatever language I searched for two years ago’” and wah lah, I had a multitude of repositories to explore how this worked. I believe I wrote a rather awful implementation of one in C++ that I wouldn’t touch with a stick now, but I settled on remaking it about a year later in Python which served my purposes at the time and satisfied my quest to understand how it worked.

Mario Ascii Image

Fast forward to a month ago and I had another epiphany when one of my friends linked yet another ascii art image, but this time I wasn’t interested in how it worked as I already knew this. What came to mind this time was making a web service to programmatically send back the ascii version of whatever image you sent it. Easy enough I thought, and turns out the webservice aspect of it was rather simple in the long run. I wanted to refresh my memory of the topic again so this time I chose to search up “Ascii art golang” as it’s the language I’ve been enjoying the most lately. That led me to this wonderful repository which works great and was surprisingly short coming in it at only 67 lines. For the most part this library fit the bill and I don’t think there are many improvements I could have made to it to make the actual image to text conversion better. What I did need to implement was getting that text back into an image, and this was the hard part.

So back to the old Google search I went looking up a majority of different things but mostly a variation of “Golang text to image”. This led me to a repository maintained by the official Go github account called “freetype”. Now to someone reading this who knows what Freetype is and how important and widely used it is this might make you cringe, but I did not know what Freetype was. After hours of getting dragged away by reading how Freetype is used instead of actually doing what I set out to do, I had come to the shocking conclusion that this could indeed be used to complete my task. If you’re reading this and don’t know what Freetype is either I’m not going to explain it here because it could be 100 articles by itself but instead I’ll link to the Wikipedia page that I used to get a better understanding of it.

Freetype logo

Now onto the code and implementation. Because we’re going to draw text to a bitmap image we first need a font file gasps. The freetype repository comes with a couple of fonts in the testdata directory which I used for the project, specifically the one I ended up settling on was the luximr font in truetype format (.ttf file extension). The freetype repo also has some great examples showing how this can be used and my implementation borrows heavily from the example in the directory named “freetype”. It takes a slice of strings and prints them to an image line by line.

If you’re wondering what the function Asset is it’s generated by a tool called go-bindata which lets you embed the bytes of files into the binary you’ll ultimately produce with your program. So Asset(“luximr.ttf”) is just getting the bytes of the font file. Other than that the freetype library makes it extremely easy to render font to an image. Because this function returns an image.Image and we obviously would prefer an encoded and viewable image we need to do just that.

Now that the implementations out of the way, we can focus on the web part of things. I chose to go with AWS Lambda hooked up to an AWS API Gateway endpoint as it’s low cost (with the amount of requests that I was expecting to receive at least) and extremely easy to get set up with a go project. The only gray area in going with Lambda and Gateway was how would binary data be handled. It turns out that API Gateway does support binary media transfers but I found this out after I had already thought to just Base64 encode the image and gotten it working(which is what they end up doing anyway).

That is pretty much the entirety of the lambda function besides a little error handling at the top and the short “lambda.Start(PostHandler)” in main. Now let’s try it out! Sending this picture of the infamous Pikachu meme Base64 encoded returns this.

Pikachu Meme Open Mouth
Pikachu Ascii Image

Now we can hook this up to a Discord bot and we can come full circle in this journey.

Discord Bot Test

Cool! If you’d like to see the source code here you go and big thanks to stdupp for the original goasciiart package and the go team and all the contributors on the freetype package!