使用“浮点数”绘制图像

时间:2019-08-23 08:32:30

标签: c# go drawing

当前,我正在尝试将现有的C#项目转换为GoLang。 该项目需要一个XML文件,该文件包含一堆坐标并将其绘制在图像上。

在C#中,用于在图像上绘制矩形的代码如下:

this.socket.on('newMessage', function(event) {
    this.dataSource.data = [...this.dataSource.data, event];
});

矩形由以下类定义:

this.socket.on('newMessage', function(event) {
    this.dataSource.data = this.dataSource.data.concat(event);
});

这意味着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); } } 的坐标在图像上绘制矩形。

现在,我正在尝试将代码转换为GoLang,在其中使用以下代码绘制矩形:

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

使用以下结构定义矩形:

float

Go中的示例不起作用,因为图像上的// 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参数在图像上绘制矩形?

1 个答案:

答案 0 :(得分:0)

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

At(x, y int) color.Color

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

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

最简单的解决方案是将float坐标转换为整数坐标。简单地将浮点转换为整数就是截断,因此您应该使用舍入。一个简单的舍入是在转换之前添加0.5。有关详细信息,请参见Golang Round to Nearest 0.05

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

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处一段距离。如果线不是水平和垂直的,但是需要更多的计算(因此速度会更慢),这种混叠技术肯定会带来更好的结果。

如果在绘制时确实需要浮动精度,则可以使用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)

另请参阅相关内容:Draw a rectangle in Golang?