web-dev-qa-db-fra.com

Comment ajouter une simple étiquette de texte à une image dans Go?

Donné image.RGBA, les coordonnées et une ligne de texte, comment ajouter une étiquette simple avec une police fixe simple? Par exemple. Face7x13 de 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?
}

L'alignement n'a pas vraiment d'importance, mais mieux si je pouvais écrire l'étiquette au-dessus d'une ligne qui commence aux coordonnées.

Et je voudrais éviter les dépendances externes chargeables comme les polices.

29
sanmai

Le package golang.org/x/image/font définit simplement les interfaces pour les faces de police et le dessin de texte sur les images.

Vous pouvez utiliser l'implémentation Go du trameur de polices Freetype: github.com/golang/freetype .

Le type de clé est freetype.Context , il a toutes les méthodes dont vous avez besoin.

Pour un exemple complet, consultez ce fichier: example/freetype/main.go . Cet exemple charge un fichier de police, crée et configure freetype.Context, Dessine du texte sur l'image et enregistre l'image résultante dans un fichier.

Supposons que le fichier de police soit déjà chargé et qu'un contexte c soit configuré (voir l'exemple comment faire). Votre fonction addLabel() pourrait alors ressembler à ceci:

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
    }
}

Si vous ne voulez pas vous tracasser avec le package freetype et les fichiers de polices externes, le package font/basicfont contient une police de base nommée Face7x13 Dont le graphique les données sont entièrement autonomes. Voici comment vous pouvez utiliser cela:

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.Int26_6(x * 64), fixed.Int26_6(y * 64)}

    d := &font.Drawer{
        Dst:  img,
        Src:  image.NewUniform(col),
        Face: basicfont.Face7x13,
        Dot:  point,
    }
    d.DrawString(label)
}

Voici comment utiliser cette fonction addLabel(): le code ci-dessous crée une nouvelle image, dessine le texte "Hello Go" Dessus et l'enregistre dans un fichier nommé 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)
    }
}

Notez que le code ci-dessus nécessite également l'importation du package "image/png" .

Notez également que la coordonnée y donnée sera la dernière ligne du texte. Donc, si vous voulez tracer une ligne dans le coin supérieur gauche, vous devez utiliser x = 0 Et y = 13 (13 est la hauteur de cette police Face7x13). Si vous le souhaitez, vous pouvez l'intégrer dans la fonction addLabel() en soustrayant 13 De la coordonnée y, de sorte que la coordonnée y transmise soit la coordonnée supérieure à laquelle le texte sera dessiné.

Il y a aussi une police autonome supplémentaire dans le paquet golang.org/x/image/font/inconsolata avec un style régulier et gras, pour les utiliser, il vous suffit de spécifier un autre Face dans 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,
42
icza

voici l'exemple de code utilisant la bibliothèque gg où nous avons déjà src.jpg ou n'importe quelle image et nous écrivons du texte dessus .. vous pouvez ajuster la taille du canevas en conséquence .. c'est juste un exemple. faites-moi savoir si cela ne fonctionne pas.

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")
}
7
Yatender Singh