2016-07-11 48 views
17

Biorąc pod uwagę image.RGBA, współrzędne i linię tekstu, w jaki sposób dodać prostą etykietę z jakąkolwiek zwykłą czcionką? Na przykład. Face7x13 z font/basicfont.Jak dodać prostą etykietę tekstową do obrazu w folderze Go?

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

Wyrównanie nie ma większego znaczenia, ale najlepiej, gdybym mógł napisać etykietę powyżej linii zaczynającej się od współrzędnych.

I chciałbym uniknąć zewnętrznych obciążalnych zależności, takich jak czcionki.

+0

Pakiet ten wyraźnie stwierdza, że ​​zapewnia tylko interfejs dla powierzchni czcionek. '" Inne pakiety zapewniają implementacje czcionek. Na przykład, pakiet truetype zapewniłby taki oparty na plikach czcionek .ttf. "' –

Odpowiedz

20

Pakiet definiuje interfejsy dla czcionek i rysowania tekstu na obrazach.

Możesz użyć implementacji Go z frezerem czcionek Freetype: github.com/golang/freetype.

Typ klucza to freetype.Context, ma wszystkie potrzebne metody.

Aby uzyskać pełny przykład, sprawdź ten plik: example/freetype/main.go. Ten przykład ładuje plik czcionki, tworzy i konfiguruje freetype.Context, rysuje tekst na obrazie i zapisuje wynikowy obraz do pliku.

Załóżmy, że masz już załadowany plik czcionki i skonfigurowano kontekst c (zobacz przykład jak to zrobić). Wówczas funkcja addLabel() mógłby wyglądać następująco:

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

Jeśli nie chcesz kłopotów z plikami freetype pakiet i czcionek zewnętrzny, pakiet font/basicfont zawiera podstawową czcionkę o nazwie Face7x13 którego graficzny dane są całkowicie samowystarczalny . W ten sposób można użyć, aby:

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

to jak to addLabel() funkcja może być używana: poniższy kod tworzy nowy obraz rysuje tekst "Hello Go" na niego i zapisuje je w pliku o nazwie 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) 
    } 
} 

Uwaga powyższy kod wymaga również importu pakietu "image/png".

Należy również pamiętać, że podana współrzędna y będzie dolną linią tekstu. Jeśli więc chcesz narysować linię w lewym górnym rogu, musisz użyć x = 0 i y = 13 (13 to wysokość tej czcionki Face7x13). Jeśli chcesz, możesz to zbudować w funkcji addLabel(), odejmując 13 od współrzędnej y, aby podana współrzędna y była najwyższą współrzędną, w której zostanie narysowany tekst.

Istnieje również dodatkowe czcionki samowystarczalny w pakiecie golang.org/x/image/font/inconsolata z regularnym i odważny styl, aby z nich korzystać, trzeba tylko podać inny Face w 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, 
+0

@sanmai Zobacz edytowaną odpowiedź, Podaję przykład użycia 'basicfont.Face7x13'. – icza

+0

dzięki, właśnie o tym! Tylko drukuje linie [połowa cut] (http://i.imgur.com/sPoxcAb.png) – sanmai

+0

@sanmai Czy Twój "img" jest wystarczająco duży? Może to jest przerywane, ponieważ umieścisz tekst pod spodem obrazu? – icza

3

oto przykładowy kod używając biblioteki gg, w której mamy już plik src.jpg lub jakikolwiek obraz i piszemy nad nim tekst. Możesz dostosować rozmiar płótna odpowiednio. To tylko przykład. daj mi znać, jeśli to nie zadziała.

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