DEV Community

Josemy Duarte
Josemy Duarte

Posted on • Originally published at josemyduarte.github.io

Putting Text on an Image with Golang

Since the beginning of my career, I have been focused on Java as my main programming language, but recently I switched to a company that uses Golang, and to help me to learn more about the language I decided to build something.

The service that I build in summary just puts some text on a given image. Its main purpose is to help me create the posts that I publish on my Instagram account DevsQuotes.

I used to create my posts with Photoshop but it was taking me too much time to get a simple image ready, then I discovered Adobe Spark which simplified the flow a little, but with this service now is super simple since I integrated it with a Telegram Bot and now I just need to send a message and I have my image ready to be published. Yes, there is room for improvement, but keep in mind that this was just a PoC which mission was to help me get comfortable with GoLang and simplify the process to create images for my Instagram.

TL;DR Show me the code!

type Request struct {
    BgImgPath string
    FontPath  string
    FontSize  float64
    Text      string
}

func TextOnImg(request Request) (image.Image, error) {
    bgImage, err := gg.LoadImage(request.BgImgPath)
    if err != nil {
        return nil, err
    }
    imgWidth := bgImage.Bounds().Dx()
    imgHeight := bgImage.Bounds().Dy()

    dc := gg.NewContext(imgWidth, imgHeight)
    dc.DrawImage(bgImage, 0, 0)

    if err := dc.LoadFontFace(request.FontPath, request.FontSize); err != nil {
        return nil, err
    }

    x := float64(imgWidth / 2)
    y := float64((imgHeight / 2) - 80)
    maxWidth := float64(imgWidth) - 60.0
    dc.SetColor(color.White)
    dc.DrawStringWrapped(request.Text, x, y, 0.5, 0.5, maxWidth, 1.5, gg.AlignCenter)

    return dc.Image(), nil
}
Enter fullscreen mode Exit fullscreen mode

That piece of code makes all the magic. With the help of Fogleman library manipulating images in Go is a breeze. Let's check what this is doing:

bgImage, err := gg.LoadImage(request.BgImgPath)
Enter fullscreen mode Exit fullscreen mode

It loads the image in which the text will be printed.

imgWidth := bgImage.Bounds().Dx()
imgHeight := bgImage.Bounds().Dy()
Enter fullscreen mode Exit fullscreen mode

Records the Width and Height of the image.

dc := gg.NewContext(imgWidth, imgHeight)
dc.DrawImage(bgImage, 0, 0)
Enter fullscreen mode Exit fullscreen mode

Creates something like a canvas (or context) in which we are going to start working.

dc.LoadFontFace(request.FontPath, request.FontSize)
Enter fullscreen mode Exit fullscreen mode

It loads the font to use on the message to be printed.

x := float64(imgWidth / 2)
y := float64((imgHeight / 2) - 80)
Enter fullscreen mode Exit fullscreen mode

Records the middle of the image on X and in Y it also subtracts 80 because I want the text to be a little bit above the middle.

maxWidth := float64(imgWidth) - 60.0
Enter fullscreen mode Exit fullscreen mode

We define the maximum width that your text can occupy. Subtracting 60 from the total width of the image is like generating a margin, so our text does not reach the edge of our image.

dc.SetColor(color.White)
Enter fullscreen mode Exit fullscreen mode

We are defining the color in which we are going to paint/print

dc.DrawStringWrapped(request.Text, x, y, 0.5, 0.5, maxWidth, 1.5, gg.AlignCenter)
Enter fullscreen mode Exit fullscreen mode

It prints the content of request.Text on our canvas in the middle of the image with an alignment centered.

The result will look like this:

PrinterExample

For more context on how all this works and even try it by yourself if you want visit the DevsQuotesPrinter repository. It has instructions for you to be able to deploy it on GCP, Heroku or to try it locally, so feel free to play with it.

Top comments (0)