How to add a simple text label to an image in Go?
Given image.RGBA
, coordinates, and a line of text, how do I add a simple label with any plain fixed font? E.g. Face7x13
from font/basicfont
.
package main
import (
"image"
"image/color"
"image/png"
"os"
)
func main() {
img := image.NewRGBA(image.Rect(0, 0, 320, 240))
x, y := 100, 100
addLabel(img, x, y, "Test123")
png.Encode(os.Stdout, img)
}
func addLabel(img *image.RGBA, x, y int, label string) {
col := color.Black
// now what?
}
Alignment doesn't really matter, but best if I could write the label above a line which starts at the coordinates.
And I would like to avoid external loadable dependencies like fonts.
The golang.org/x/image/font
package just defines interfaces for font faces and drawing text on images.
You may use the Go implementation of Freetype font rasterizer: github.com/golang/freetype
.
The key type is freetype.Context
, it has all the methods you need.
For a complete example, check out this file: example/freetype/main.go
. This example loads a font file, creates and configures freetype.Context
, draws text on image and saves the result image to file.
Let's assume you already have the font file loaded, and a c
context configured (see the example how to do that). Then your addLabel()
function could look like this:
func addLabel(img *image.RGBA, x, y int, label string) {
c.SetDst(img)
size := 12.0 // font size in pixels
pt := freetype.Pt(x, y+int(c.PointToFixed(size)>>6))
if _, err := c.DrawString(label, pt); err != nil {
// handle error
}
}
If you don't want to hassle with the freetype
package and external font files, the font/basicfont
package contains a basic font named Face7x13
whose graphical data is entirely self-contained. This is how you could use that:
import (
"golang.org/x/image/font"
"golang.org/x/image/font/basicfont"
"golang.org/x/image/math/fixed"
"image"
"image/color"
)
func addLabel(img *image.RGBA, x, y int, label string) {
col := color.RGBA{200, 100, 0, 255}
point := fixed.Point26_6{fixed.I(x), fixed.I(y)}
d := &font.Drawer{
Dst: img,
Src: image.NewUniform(col),
Face: basicfont.Face7x13,
Dot: point,
}
d.DrawString(label)
}
This is how this addLabel()
function can be used: the code below creates a new image, draws the "Hello Go"
text on it and saves it in a file named hello-go.png
:
func main() {
img := image.NewRGBA(image.Rect(0, 0, 300, 100))
addLabel(img, 20, 30, "Hello Go")
f, err := os.Create("hello-go.png")
if err != nil {
panic(err)
}
defer f.Close()
if err := png.Encode(f, img); err != nil {
panic(err)
}
}
Note the above code also requires the "image/png"
package import.
Also note that the y
coordinate given will be the bottom line of the text. So if you want to draw a line to the top left corner, you have to use x = 0
and y = 13
(13 is the height of this Face7x13
font). If you wish, you could build this into the addLabel()
function by subtracting 13
from the y
coordinate, so that the passed y
coordinate would be the top coordinate at which the text will be drawn.
There is also an additional self-contained font in the golang.org/x/image/font/inconsolata
package with regular and bold style, to use them, you only need to specify a different Face
in addLabel()
:
import "golang.org/x/image/font/inconsolata"
// To use regular Inconsolata font family:
Face: inconsolata.Regular8x16,
// To use bold Inconsolata font family:
Face: inconsolata.Bold8x16,
here is the sample code using gg library where we already have src.jpg or any image and we write text over it.. you can adjust canvas size accordingly .. it's just example. let me know if it doesn't work.
package main
import (
"github.com/fogleman/gg"
"log"
)
func main() {
const S = 1024
im, err := gg.LoadImage("src.jpg")
if err != nil {
log.Fatal(err)
}
dc := gg.NewContext(S, S)
dc.SetRGB(1, 1, 1)
dc.Clear()
dc.SetRGB(0, 0, 0)
if err := dc.LoadFontFace("/Library/Fonts/Arial.ttf", 96); err != nil {
panic(err)
}
dc.DrawStringAnchored("Hello, world!", S/2, S/2, 0.5, 0.5)
dc.DrawRoundedRectangle(0, 0, 512, 512, 0)
dc.DrawImage(im, 0, 0)
dc.DrawStringAnchored("Hello, world!", S/2, S/2, 0.5, 0.5)
dc.Clip()
dc.SavePNG("out.png")
}