使用System.Drawing.DrawLine从控制台应用程序中绘制多个线条/形状

时间:2017-07-12 13:56:18

标签: c# bitmap console-application

我正在为我的作品编写一个程序,它将采用自定义的方向代码格式,并根据给定的代码绘制形状,并将结果保存到图像中。

示例:

  

SQR = W10 S10 E10 N10 $。

在图像上输出10x10的正方形形状( N,S,E和W 是方向)。

我知道如何使用 OnPaint 与WPF应用程序完成此操作,但我需要通过控制台应用程序完成此操作。我已经解析了所有数据以及类和集合,因此我所要做的就是绘制。但是我遇到了记忆问题;它一次只绘制一行而不保存前一行。

我部分绘制的代码是:

Pen pen = new Pen(Color.Black, 2);
Bitmap bmp = new Bitmap(xMax, yMax);

using (var graphics = Graphics.FromImage(bmp))
{
    graphics.FillRectangle(Brushes.White, new Rectangle(0, 0, xMax, yMax));

    foreach (Line line in lines)
    {
        graphics.DrawLine(pen, line.start, line.end);
    }
}

bmp.Save("test.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);

以下是我使用 DrawLines 的代码,而不是:

Pen pen = new Pen(Color.Black, 2);
Bitmap bmp = new Bitmap(xMax, yMax);

using (var graphics = Graphics.FromImage(bmp))
{
    graphics.FillRectangle(Brushes.White, new Rectangle(0, 0, xMax, yMax));

    Point[] pts = new Point[lines.Count];
    int i = 0;

    pts[0] = lines[0].start; // This sets the starting point.

    foreach (Line line in lines)
    {
        pts[i] = line.end;
        i++;
    }

    graphics.DrawLines(pen, pts);
}

bmp.Save("test.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);

这是我的类:

class Line
{
    public Point start { get; set; }
    public Point end { get; set; }
}

这是我在绘图之前的点列表:

enter image description here

使用System.Drawing和控制台应用程序执行此操作有哪些选择,并允许它将所有行保存到生成的图像中?

2 个答案:

答案 0 :(得分:2)

以下是您需要更改的内容:

首先,我们将这些行转换为List<T> Points

List<Point> points = lines.Select(x => x.start).ToList();
points.Add(lines.Last().end);

(我总是尽量避免使用数组,列表可以更好地使用...)

现在我们确定x和y值的最小值:

int minX = points.Select(x => x.X).Min();
int minY = points.Select(x => x.Y).Min();

然后我们移动graphics视口将它们全部放入:

graphics.TranslateTransform( -minX, -minY);

现在我们可以一次性绘制它们:

graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; // optional
using (Pen pen = new Pen(Color.Black, 2)
{ LineJoin = System.Drawing.Drawing2D.LineJoin.Round })
    graphics.DrawLines(pen, points.ToArray());

一些注意事项:

  • 我没有检查最大值!如果那些太大,我们仍然会丢失一些线或线段..

  • DrawLines的一大优势:半透明笔可以很好地工作,即正确绘制重叠的末端。

  • 我已将笔创作移到绘图中;随意把它放在你想要的地方,但确保完成后Pen处理

  • 我还设置了LineJoin;和他们玩吧!当笔宽变得非常大时,您将看到效果。

答案 1 :(得分:1)

显示填充lines集合的代码。在该代码中放置一个断点并检查您的行列表并验证集合中是否有多行。

我使用了以下代码(使用您的Line类)并且它工作正常并绘制了所有行。

void Main()
{
    int xMax, yMax;
    xMax = 512;
    yMax = 512;

    //Create a list of lines to draw.
    var lines = new List<Line>
    {
        new Line
        {
            Start = new Point(5, 5),
            End =  new Point(50, 50)
        },
        new Line
        {
            Start = new Point(100, 20),
            End =  new Point(50, 90)
        },
        new Line
        {
            Start = new Point(35, 75),
            End =  new Point(500, 400)
        },
    };

    //Declare the Bitmap, Graphics, and Pen in a using block so
    //they are all disposed properly when finished.        
    using (var bmp = new Bitmap(xMax, yMax))
    using (var graphics = Graphics.FromImage(bmp))
    using (var pen = new Pen(Color.Black, 2))
    {
        graphics.FillRectangle(Brushes.Green, new Rectangle(0, 0, xMax, yMax));

        foreach (Line line in lines)
        {
            graphics.DrawLine(pen, line.Start, line.End);
        }

        bmp.Save(@"g:\test\test.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
    }
}

注意:务必处置图形对象(图形,笔和位图),以免泄漏资源。最好的方法是使用using块。

**我看到我迟到了。无论如何,我会把它留在这里,以防它帮助其他人。