【问题标题】:Using System.Drawing.DrawLine to draw multiple lines/shapes from console application使用 System.Drawing.DrawLine 从控制台应用程序中绘制多条线/形状
【发布时间】:2017-07-12 23:06:56
【问题描述】:

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

例子:

SQR=W10 S10 E10 N10$.

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

我知道如何通过 WPF 应用程序使用 OnPaint 来完成这项工作,但我需要通过控制台应用程序来完成这项工作。我已经解析了所有的数据,并在类和集合中,所以我所要做的就是绘制。但我无法解决内存问题;它一次只画一条线,不保存前面的线。

我部分绘制的代码是:

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

这是我的 Line 类:

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

这是我的点列表在绘制之前的样子:

我有哪些选项可以使用 System.Drawing 和控制台应用程序,并允许它将所有线条保存到生成的图像中?

【问题讨论】:

  • 一定要使用 DrawLines 方法以获得更好的质量!它需要一个点数组,因此您应该重写创建线的代码。除此之外,代码看起来不错。我假设您确实包含了必要的参考资料..?你能显示line 类吗?
  • 我也尝试了 DrawLines,但我仍然只能得到同一条线。我可以展示 Line 类(它改编自我采用的不同路线,所以它并不完美,但它应该仍然有效)
  • 我怀疑你的数据。 - 顺便说一句:我的意思是收集 List 中的所有点并一次性绘制它们:DrawLines(pen, points.ToArray());
  • 我先看看Line集合写在画之前。
  • 但是 DrawLines 只是用来绘制连续的,即连接的线!如果您需要单独的行,您的原始代码将尽可能好!

标签: c# bitmap console-application


【解决方案1】:

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

首先我们将这些行转换为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;和他们一起玩!当笔宽变得非常大时,您会看到效果..

【讨论】:

  • 现在画得好多了。谢谢!
【解决方案2】:

显示填充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 块。

**我知道我参加聚会迟到了。无论如何我都会把它留在这里,以防它帮助别人。

【讨论】:

  • 错误在于我的观点是负面的,因此它们没有显示在结果图像上。不过还是谢谢你的回答!我相信它会帮助其他人!
  • @Chris-dunaway 有趣的是,您如何能够在控制台应用程序中使用Graphics?当我使用Graphics.FromImage() 时,我收到一条错误消息:Encapsulates GDI+ surface。这个类不能被继承...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-12-04
  • 1970-01-01
  • 1970-01-01
  • 2011-08-25
  • 1970-01-01
  • 2011-12-01
  • 1970-01-01
相关资源
最近更新 更多