Provide a service for animated gif creation
Animated GIF Service
This example will provide a HTTP service that creates animated GIF containing the text that is passed as input to the service.The service uses the standard library of Go and some additional libraries:
- the image is produced using the standard library image
- the text written inside the image is generated using the library freetype (https://github.com/golang/freetype)
- the HTTP service is activated using the framework Gin-Gonic (https://github.com/gin-gonic/gin)
What we get is a service that responds to requests like these
http://localhost:8000/animated.gif?name=Max
generating images like this
Create the GIF Image
The package image/gif provides all the methods and structures to operate with GIF image format.
// Generate an animated gif
func GenerateAnimation(text string, fontfile string, out io.Writer) {
const (
nframes = 64 // number of animation frames
delay =8 // delay between frames in 10ms units
)
var xsize int = 40 + 30 * len(text)
var ysize int = 200
//load the font ...
var palette = make([]color.Color,0)
// generate palette
for i := 0; i < nframes; i++ {
palette = append(palette, color.RGBA{R:0,G:0,B:uint8(4*i), A:255})
}
anim := gif.GIF{LoopCount: nframes}
for i := 0; i < nframes; i++ {
rect := image.Rect(0, 0, xsize, ysize)
img := image.NewPaletted(rect, palette)
for x := 0; x < xsize; x++ {
for y := 0; y < ysize; y++ {
img.SetColorIndex(x, y, uint8(i))
}
}
WriteText(text, f, img)
anim.Delay = append(anim.Delay, delay)
anim.Image = append(anim.Image, img)
}
gif.EncodeAll(out, &anim)
}The function GenerateAnimation first creates the palette and then performs a loop to add the images that compose the animation assigning an identical delay to every frame.
The function WriteText is called before adding the image to the GIF.
Add the text to the image
First load the TrueType Font, this is done in the function GenerateAnimation
// Read the font data.
fontBytes, err := ioutil.ReadFile(fontfile)
if err != nil {
log.Println(err)
return
}
f, err := freetype.ParseFont(fontBytes)
if err != nil {
log.Println(err)
return
}
The font is passed to the method that writes the text// Write a text inside the image
func WriteText(text string, f *truetype.Font, img *image.Paletted){
// Initialize the context.
fg:= image.Black
c := freetype.NewContext()
c.SetDPI(72)
c.SetFont(f)
c.SetFontSize(64)
c.SetClip(img.Bounds())
c.SetDst(img)
c.SetSrc(fg)
// Draw the text.
pt := freetype.Pt(40, 120)
c.DrawString(text, pt) }The freetype library writes the text on the destination image by creating a mask from the source image. In this example, the source image is a black foreground and the destination image is a frame of the animated GIF.
Activate the HTTP service
Now we will create an HTTP service that reads the parameter name from the querystring and writes the text in the animated GIF.
Using Gin-Gonic for service activation requires a few lines of code
func main(){
router := gin.New()
// Global middleware
router.Use(gin.Logger())
router.Use(gin.Recovery())
router.GET("/animated.gif", animatedgif)
router.Run("0.0.0.0:8000")
}URI handler for /animated.gif simply calls the function GenerateAnimation
func animatedgif (c *gin.Context) {
name := c.Query("name")
GenerateAnimation("Hello " + name + " !", "luxisr.ttf", c.Writer) }
Conclusions
This simple service lends itself to be used in many ways. Actual use cases can be:
- generate dynamic banners for websites
- insert dynamic images in email like animated welcome messages, produced when the message is opened
The service can be modified to produce a counter or a reverse counter to be used also on websites and in messages or, with some more changes, the service can be easy modified to produce a lottery service (the first that displays the banner read "You have win", the next read "You lost, try again").
The full example code can be downloaded here
Commenti
Posta un commento