Dessiner un rectangle à Golang?
4 réponses
la bibliothèque Go standard ne fournit pas de capacités de dessin primitif ou de peinture.
Ce qu'il fournit des modèles pour les couleurs (image/color
paquet) et un Image
interface avec plusieurs implémentations (image
paquet). Le blog le paquet Image Go est une bonne introduction à ce.
il permet également de combiner des images (par ex. les dessiner sur chaque autres), avec des opérations dans le image/draw
package. Cela peut être utilisé à beaucoup plus que cela ne semble au début. Il ya un bel article de blog sur le image/draw
package qui met en vedette certains de ses potentiels: Go image/tirage paquet
un autre exemple est le jeu open-source labyrinthe de Gopher (divulgation: je suis l'auteur) qui a une interface graphique et n'utilise rien d'autre que le bibliothèque Go standard pour assembler sa vue.
c'est open source, vérifiez ses sources comment c'est fait. Il a une vue de jeu avec des images/animations en mouvement.
la bibliothèque standard prend également en charge la lecture et l'écriture de formats d'image communs comme GIF, JPEG,PNG, et le support d'autres formats sont disponibles de la boîte: BMP, RIFF, TIFF et même WEBP (seulement un lecteur/décodeur).
bien que le support ne soit pas fourni par la bibliothèque standard, il est assez facile de dessiner des lignes et des rectangles sur une image. Compte tenu de l' img
image qui prend en charge la modification d'un pixel avec une méthode: Set(x, y int, c color.Color)
(par exemple image.RGBA
est parfait pour nous) et un col
de type color.Color
:
// HLine draws a horizontal line
func HLine(x1, y, x2 int) {
for ; x1 <= x2; x1++ {
img.Set(x1, y, col)
}
}
// VLine draws a veritcal line
func VLine(x, y1, y2 int) {
for ; y1 <= y2; y1++ {
img.Set(x, y1, col)
}
}
// Rect draws a rectangle utilizing HLine() and VLine()
func Rect(x1, y1, x2, y2 int) {
HLine(x1, y1, x2)
HLine(x1, y2, x2)
VLine(x1, y1, y2)
VLine(x2, y1, y2)
}
utilisation de ces fonctions simples voici un exemple de programme exécutable qui dessine une ligne et un rectangle et sauve l'image dans un .png
fichier:
import (
"image"
"image/color"
"image/png"
"os"
)
var img = image.NewRGBA(image.Rect(0, 0, 100, 100))
var col color.Color
func main() {
col = color.RGBA{255, 0, 0, 255} // Red
HLine(10, 20, 80)
col = color.RGBA{0, 255, 0, 255} // Green
Rect(10, 10, 80, 50)
f, err := os.Create("draw.png")
if err != nil {
panic(err)
}
defer f.Close()
png.Encode(f, img)
}
Si vous voulez dessiner des textes, vous pouvez utiliser le mise en œuvre de FreeType. Consultez également cette question pour une introduction simple au dessin des chaînes sur les images:comment ajouter une étiquette de texte simple à une image dans Go?
si vous voulez des capacités de dessin avancées et plus complexes, il y a aussi de nombreuses bibliothèques externes disponible, par exemple:
vous cherchez probablement le draw2d paquet. De leur github
readme:
les opérations de draw2d incluent le Strike et le remplissage des polygones, des arcs, des courbes de Bézier, le dessin des images et le rendu de texte avec des polices truetype. Toutes les opérations de dessin peuvent être transformées par des transformations affines (échelle, rotation, translation).
Le code suivant dessine un rectangle noir et l'écrit dans un .png
fichier. Il utilise le v1 libération (go get -u github.com/llgcode/draw2d
).
package main
import (
"github.com/llgcode/draw2d/draw2dimg"
"image"
"image/color"
)
func main() {
i := image.NewRGBA(image.Rect(0, 0, 200, 200))
gc := draw2dimg.NewGraphicContext(i)
gc.Save()
gc.SetStrokeColor(color.Black)
gc.SetFillColor(color.Black)
draw2d.Rect(gc, 10, 10, 100, 100)
gc.FillStroke()
gc.Restore()
draw2dimg.SaveToPngFile("yay-rectangle.png", i)
}
consultez la page github pour la nouvelle version.
Voici comment dessiner deux rectangles en utilisant les bibliothèques golang standard
// https://blog.golang.org/go-imagedraw-package
package main
import (
"image"
"image/color"
"image/draw"
"image/png"
"os"
)
func main() {
new_png_file := "/tmp/two_rectangles.png"
myimage := image.NewRGBA(image.Rect(0, 0, 220, 220)) // x1,y1, x2,y2
mygreen := color.RGBA{0, 100, 0, 255} // R, G, B, Alpha
// backfill entire surface with green
draw.Draw(myimage, myimage.Bounds(), &image.Uniform{mygreen}, image.ZP, draw.Src)
red_rect := image.Rect(60, 80, 120, 160) // geometry of 2nd rectangle
myred := color.RGBA{200, 0, 0, 255}
// create a red rectangle atop the green surface
draw.Draw(myimage, red_rect, &image.Uniform{myred}, image.ZP, draw.Src)
myfile, _ := os.Create(new_png_file) // ... now lets save imag
png.Encode(myfile, myimage)
}
ci-dessus va générer un fichier png avec nos deux rectangles :
le code suivant va créer une image d'échiquier à partir de rectangles
package main
import (
"fmt"
"image"
"image/color"
"image/draw"
"image/png"
"os"
)
func main() {
new_png_file := "/tmp/chessboard.png"
board_num_pixels := 240
myimage := image.NewRGBA(image.Rect(0, 0, board_num_pixels, board_num_pixels))
colors := make(map[int]color.RGBA, 2)
colors[0] = color.RGBA{0, 100, 0, 255} // green
colors[1] = color.RGBA{50, 205, 50, 255} // limegreen
index_color := 0
size_board := 8
size_block := int(board_num_pixels / size_board)
loc_x := 0
for curr_x := 0; curr_x < size_board; curr_x++ {
loc_y := 0
for curr_y := 0; curr_y < size_board; curr_y++ {
draw.Draw(myimage, image.Rect(loc_x, loc_y, loc_x+size_block, loc_y+size_block),
&image.Uniform{colors[index_color]}, image.ZP, draw.Src)
loc_y += size_block
index_color = 1 - index_color // toggle from 0 to 1 to 0 to 1 to ...
}
loc_x += size_block
index_color = 1 - index_color // toggle from 0 to 1 to 0 to 1 to ...
}
myfile, err := os.Create(new_png_file)
if err != nil {
panic(err.Error())
}
defer myfile.Close()
png.Encode(myfile, myimage) // ... save image
fmt.Println("firefox ", new_png_file) // view image issue : firefox /tmp/chessboard.png
}
ma prise de vue noob à dessiner un rectangle d'épaisseur de ligne donnée. Encore primitive
func Rect(x1, y1, x2, y2, thickness int, img *image.RGBA) {
col := color.RGBA{0, 0, 0, 255}
for t:=0; t<thickness; t++ {
// draw horizontal lines
for x := x1; x<= x2; x++ {
img.Set(x, y1+t, col)
img.Set(x, y2-t, col)
}
// draw vertical lines
for y := y1; y <= y2; y++ {
img.Set(x1+t, y, col)
img.Set(x2-t, y, col)
}
}
}
// handler to test
func draw(w http.ResponseWriter, r *http.Request) {
img := image.NewRGBA(image.Rect(0, 0, 1200, 1800))
Rect(5, 5, 1195, 1795, 2, img)
png.Encode(w, img)
}