为了账号安全,请及时绑定邮箱和手机立即绑定

用“浮点数”绘制图像

用“浮点数”绘制图像

Go
一只名叫tom的猫 2023-07-17 14:22:06
目前,我正在尝试将现有的 C# 项目转换为 GoLang。该项目采用一个包含一堆坐标的 XML 文件并将它们绘制在图像上。在 C# 中,在图像上绘制矩形的代码如下:public void DrawRectangle(Graphics graphics, RectangleShape rectangle){    using (var drawingPen = new Pen(Color.Black))    {        graphics.DrawRectangle(            drawingPen,            rectangle.StartX,            rectangle.StartY,            rectangle.Width,            rectangle.Height);    }}矩形由以下类定义:internal sealed class RectangleShape{    internal RectangleShape(float startX, float startY, float width, float height)    {        this.StartX = startX;        this.StartY = startY;        this.Width = width;        this.Height = height;    }    internal float StartX { get; }    internal float StartY { get; }    internal float Width { get; }    internal float Height { get; }}这意味着 C# 能够使用定义为 的坐标在图像上绘制矩形float。现在,我尝试将代码转换为 GoLang,其中我使用以下代码绘制一个矩形:// DrawRect draws a rectangle with the given dimensions on the given image.func DrawRect(img *image.RGBA, rect Rectangle) {    endX := rect.X + rect.Width    endY := rect.Y + rect.Height    drawHLine(img, rect.X, rect.Y, endX)    drawHLine(img, rect.Y, endY, endX)    drawVLine(img, rect.Y, rect.X, endY)    drawVLine(img, rect.Y, endX, endY)}// PRIVATE: drawHLine draws a horizontal line with the given coordinates on the given image.func drawHLine(img *image.RGBA, startX, y, endX float32) {    col := color.RGBA{0x00, 0x00, 0x00, 0xff}    for ; startX <= endX; startX++ {        img.Set(startX, y, col)    }}// PRIVATE: drawVLine draws a vertical line with the given coordinates on the given image.func drawVLine(img *image.RGBA, startY, x, endY float32) {    col := color.RGBA{0x00, 0x00, 0x00, 0xff}    for ; startY <= endY; startY++ {        img.Set(x, startY, col)    }}矩形由以下结构定义:// Rectangle represents a rectangular shape.type Rectangle struct {    X      float32    Y      float32    Width  float32    Height float32}Go 中的示例不起作用,因为Set图像上的函数具有以下结构:func (p *RGBA) Set(x, y int, c color.Color) {Go 有什么办法可以使用float参数在图像上绘制矩形吗?
查看完整描述

1 回答

?
烙印99

TA贡献1829条经验 获得超13个赞

image.Image类型是一个接口,它将图像定义为具有整数坐标的像素,可通过以下Image.At()方法访问:

At(x, y int) color.Color

您使用的具体实现image.RGBA允许再次使用整数坐标和方法来更改像素RGBA.Set()

func (p *RGBA) Set(x, y int, c color.Color)

最简单的解决方案是将浮点坐标转换为整数坐标。简单地将浮点转换为整数就是截断,因此您应该使用舍入。0.5在转换之前添加一个简单的舍入。

最好是在“开始”坐标上执行此操作,以便循环可以使用整数值,例如:

func drawHLine(img *image.RGBA, startX, y, endX float32) {

    col := color.RGBA{0x00, 0x00, 0x00, 0xff}


    x1, x2 := int(startX + 0.5), int(endX + 0.5)

    y1 := int(y + 0.5)

    for x := x1; x <= x2; x++ {

        img.Set(x, y1, col)

    }

}

请注意,但是这种将浮点坐标转换为整数的“最简单”解决方案可能不是“最佳”。例如,如果您需要在坐标处绘制一条水平线x = 0.1,则上述解决方案将在 处绘制一条线x = 0。一种不同的解决方案可能是在 处画一条“较强”的线x = 0,在 处画一条“较弱”的线,从而给出从远处观察时x = 1该线实际上位于 处的效果。x = 0.1如果线条不是水平和垂直的,这种混叠技术肯定会给出更好的结果,但需要更多的计算(因此速度更慢)。

如果您在绘图时确实需要浮动精度,您可以使用第 3 方库,例如github.com/fogleman/gg它允许您传递float64坐标,并且它使用抗锯齿来实现良好的结果。

例如,在图像github.com/fogleman/gg上绘制一个矩形image.RGBA,如下所示:

var img *image.RGBA = // create your RGBA image


ctx := gg.NewContextForRGBA(img)


// Set drawing color:

ctx.SetColor(color.RGBA{0x00, 0x00, 0x00, 0xff})

// Or simply: ctx.SetRGB(0, 0, 0)


// Draw rectangle: x, y, w, h are all float64 parameters

ctx.DrawRectangle(x, y, w, h)


查看完整回答
反对 回复 2023-07-17
  • 1 回答
  • 0 关注
  • 134 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信