使用 'Floating Point Numbers' 绘制图像
Draw images with 'Floating Point Numbers'
目前,我正在尝试将现有的 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);
}
}
一个矩形由以下 class 定义:
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
参数在图像上绘制矩形吗?
image.Image
类型是一个接口,它定义了具有整数坐标像素的图像,可通过 Image.At()
方法访问:
At(x, y int) color.Color
您使用的具体实现image.RGBA
allows changing the pixels, again, using integer coordinates with the RGBA.Set()
方法:
func (p *RGBA) Set(x, y int, c color.Color)
最简单的解决方案是将浮点坐标转换为整数坐标。简单地将浮点数转换为整数是截断,因此您应该使用舍入。一个简单的舍入是在转换前添加 0.5
。有关详细信息,请参阅 。
最好是在 "start" 坐标上进行,这样循环可以使用整数值,例如:
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)
}
}
请注意,但是这个 "simplest" 将浮点坐标转换为整数的解决方案可能不是 "best"。例如,如果您需要在 x = 0.1
坐标处绘制一条水平线,则上述解决方案将在 x = 0
处绘制一条线。一个不同的解决方案可能是在 x = 0
处画一条 "stronger" 线,在 x = 1
处画一条 "weeker" 线,给出的效果是该线实际上在 x = 0.1
如果从远处看。如果线条不是水平和垂直的,这种别名技术肯定会提供更好的结果,但需要更多的计算(因此更慢)。
如果您在绘图时确实需要浮动精度,您可以使用像 github.com/fogleman/gg
这样的第 3 方库,它允许您传递 float64
坐标,并且它使用抗锯齿来获得不错的效果。
例如,在 image.RGBA
图像上绘制一个 github.com/fogleman/gg
的矩形是这样的:
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)
另见相关:
目前,我正在尝试将现有的 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);
}
}
一个矩形由以下 class 定义:
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
参数在图像上绘制矩形吗?
image.Image
类型是一个接口,它定义了具有整数坐标像素的图像,可通过 Image.At()
方法访问:
At(x, y int) color.Color
您使用的具体实现image.RGBA
allows changing the pixels, again, using integer coordinates with the RGBA.Set()
方法:
func (p *RGBA) Set(x, y int, c color.Color)
最简单的解决方案是将浮点坐标转换为整数坐标。简单地将浮点数转换为整数是截断,因此您应该使用舍入。一个简单的舍入是在转换前添加 0.5
。有关详细信息,请参阅
最好是在 "start" 坐标上进行,这样循环可以使用整数值,例如:
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)
}
}
请注意,但是这个 "simplest" 将浮点坐标转换为整数的解决方案可能不是 "best"。例如,如果您需要在 x = 0.1
坐标处绘制一条水平线,则上述解决方案将在 x = 0
处绘制一条线。一个不同的解决方案可能是在 x = 0
处画一条 "stronger" 线,在 x = 1
处画一条 "weeker" 线,给出的效果是该线实际上在 x = 0.1
如果从远处看。如果线条不是水平和垂直的,这种别名技术肯定会提供更好的结果,但需要更多的计算(因此更慢)。
如果您在绘图时确实需要浮动精度,您可以使用像 github.com/fogleman/gg
这样的第 3 方库,它允许您传递 float64
坐标,并且它使用抗锯齿来获得不错的效果。
例如,在 image.RGBA
图像上绘制一个 github.com/fogleman/gg
的矩形是这样的:
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)
另见相关: