image - atributos - etiqueta img
¿Dibujar un rectángulo en Golang? (4)
Quiero dibujar una etiqueta de correo con algunos rectángulos, códigos de barras y, finalmente, generar un archivo PNG / PDF.
¿Hay una forma mejor de dibujar una forma en Go que no sea hacerlo con primitivos, píxel por píxel?
Aquí es cómo dibujar dos rectángulos utilizando bibliotecas estándar de Golang
// 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)
}
Lo anterior generará un archivo png con nuestros dos rectángulos:
El siguiente código creará una imagen de tablero de ajedrez a partir de rectángulos.
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
}
La biblioteca estándar de Go no proporciona capacidades de dibujo o pintura primitivas.
Lo que proporciona son modelos para colores (paquete de image/color
) y una interfaz de Image
con varias implementaciones (paquete de image
). La publicación del blog The Go Image package es una buena introducción a esto.
También proporciona la capacidad de combinar imágenes (por ejemplo, dibujarlas entre sí) con diferentes operaciones en el paquete de image/draw
. Esto se puede usar para mucho más de lo que parece al principio. Hay un buen artículo de blog sobre el paquete image/draw
que muestra parte de su potencial: El paquete Go image / draw.
Otro ejemplo es el juego de código abierto Gopher''s Labyrinth ( revelación: Soy el autor ) que tiene una interfaz gráfica y no utiliza nada más que la biblioteca estándar de Go para ensamblar su vista.
Es de código abierto, echa un vistazo a sus fuentes cómo se hace. Tiene una vista de juego desplazable con imágenes / animaciones en movimiento.
La biblioteca estándar también admite la lectura y escritura de formatos de imagen comunes como GIF , JPEG , PNG , y el soporte para otros formatos están disponibles de forma WEBP : BMP , RIFF , TIFF e incluso WEBP (solo un lector / decodificador).
Aunque la biblioteca estándar no proporciona soporte, es bastante fácil dibujar líneas y rectángulos en una imagen. Dada una imagen img
que admite cambiar un píxel con un método: Set(x, y int, c color.Color)
(por ejemplo, image.RGBA
es perfecto para nosotros) y una col
de color.Color
de 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)
}
El uso de estas funciones simples aquí es un programa de ejemplo ejecutable que dibuja una línea y un rectángulo y guarda la imagen en un archivo .png
:
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 desea dibujar textos, puede usar la implementación Go de FreeType . También revise esta pregunta para obtener una introducción sencilla al dibujo de cadenas en imágenes: ¿Cómo agregar una etiqueta de texto simple a una imagen en Go?
Si desea capacidades de dibujo avanzadas y más complejas, también hay muchas bibliotecas externas disponibles, por ejemplo:
Mi noob disparó al dibujar un rectángulo de grosor de línea dado. Todavia primitivo
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)
}
Probablemente estés buscando el paquete draw2d . De su github
readme:
Las operaciones en draw2d incluyen trazos y rellenos de polígonos, arcos, curvas de Bézier, dibujo de imágenes y representación de texto con fuentes TrueType. Todas las operaciones de dibujo se pueden transformar mediante transformaciones afines (escala, rotación, traslación).
El siguiente código dibuja un rectángulo negro y lo escribe en un archivo .png
. Está utilizando la versión v1 ( 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)
}
Por favor, consulte la página de github para la versión más reciente.