在Golang中绘制一个矩形?

Fak*_*eer 23 image draw go

我想绘制带有一些矩形,条形码的邮件标签,然后最终生成一个PNG/PDF文件.

是否有一种更好的方法在Go中绘制一个形状,而不是用原始图形 - 逐个像素?

icz*_*cza 42

标准Go库不提供原始绘图或绘画功能.

它提供的是颜色模型(image/color包)和Image具有多个实现(image包)的接口.博客文章The Go Image包是对此的一个很好的介绍.

它还提供了将图像(例如,彼此绘制)与image/draw包中的不同操作组合的能力.这比起初听起来要多得多.有一篇关于该image/draw软件包的博客文章很好地展示了它的一些潜力: Go图像/绘图包

另一个例子是开源游戏Gopher's Labyrinth(披露:我是作者),它有一个图形界面,它只使用标准的Go库来组装它的视图.

Gopher's Labyrinth截图

它是开源的,查看它的来源如何完成.它有一个可滚动的游戏视图,里面有动态图像/动画.

标准库还支持读写常见的图像格式,如GIF,JPEG,PNG,并支持其他格式的开箱即用:BMP,RIFF,TIFF甚至WEBP(只有读卡器/解码器).

虽然标准库没有给出支持,但在图像上绘制线条和矩形相当容易.给定一个img支持使用方法更改像素的图像:( Set(x, y int, c color.Color)例如image.RGBA,对我们来说是完美的)和col类型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)
}
Run Code Online (Sandbox Code Playgroud)

这里使用这些简单的函数是一个可运行的示例程序,它绘制一条线和一个矩形并将图像保存到.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)
}
Run Code Online (Sandbox Code Playgroud)

如果要绘制文本,可以使用FreeTypeGo实现.另外,请查看此问题,以简单介绍图像上的图形字符串:如何在Go中为图像添加简单的文本标签?

如果您需要高级和更复杂的绘图功能,还可以使用许多外部库,例如:

https://github.com/llgcode/draw2d

https://github.com/fogleman/gg

  • icza非常感谢.我确实看到了图像pkg结构.只是无法"连接点"并找到像你在hline和vline中所做的那样内置的东西.这是我不想做的事情,因为线性算法并不简单,光栅化抗锯齿,bresenham等.我现在将尝试你的例子并学习.并且还要感谢建议freetype - 在标签上放置文本也是我的req的一部分,我忘了在问题中提出. (2认同)

Ric*_*ith 5

您可能正在寻找draw2d软件包。从他们的github自述文件:

draw2d中的操作包括描边和填充多边形,圆弧,贝塞尔曲线,绘制图像以及使用truetype字体渲染文本。可以通过仿射变换(比例,旋转,平移)来变换所有绘图操作。

下面的代码绘制一个黑色矩形并将其写入.png文件。它使用的是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)
}
Run Code Online (Sandbox Code Playgroud)

请查阅github页面以获取最新版本。


Sco*_*and 5

这是使用标准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" // output image lives here

    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, err := os.Create(new_png_file)     // ... now lets save imag
    if err != nil {
        panic(err)
    }
    png.Encode(myfile, myimage)   // output file /tmp/two_rectangles.png
}
Run Code Online (Sandbox Code Playgroud)

上面将生成带有两个矩形的png文件:

以下代码将从矩形创建棋盘图像

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
}
Run Code Online (Sandbox Code Playgroud)