保存更高分辨率的图表而不破坏外观

9
请原谅我的无知,因为我最近才开始使用C#。我有一个关于Windows图表控件的问题,因为我遇到了一个非常愚蠢的问题。
我编写了一个程序,其中包含一些报告,其中包括漂亮的Windows图表来表示某些数据。但是,我还将这些图表保存为文件以供各种用途使用,只需使用以下内容即可:
chart2.SaveImage(savefilename, ChartImageFormat.Png);
我的第一个问题在于,我不确定如何在未保存之前提高分辨率,而不是先增加图表控件的大小。最好有一张质量合理的图像。
第二个问题是,当我增加图表控件的大小时,可用的操作似乎只能增加实际图表的大小,而不能增加标签或文本的大小。如果我可以手动更改所有这些,那就不是问题了,这就是我为条形图所做的,但是有一行我无法弄粗:饼图上的标签线。我在下面的图像中画了一个箭头:

http://www.bolinger.ca/chart.png

当图表增加到合理的分辨率时,由于没有增加到适当的相对大小,这条线几乎是看不见的。我觉得应该有一种方法可以改变它,但是找不到是什么。请原谅我的无知。如果这两个问题中的任何一个能够解决,那么我就可以放心地知道这些饼图看起来不错了。谢谢!
4个回答

12
创建/复制一个在表单上隐藏(Visible = false)的图表对象。甚至可以将其Top和Left属性设置为偏离表单。将此控件设置为非常高的宽度和高度(即2100 x 1500)...按照您的规格填充和格式化它。确保增加字体大小等。然后从隐藏的图表中调用SaveImage()或DrawToBitmap()...
当您保存此文件时,它基本上具有足够高的分辨率,适用于大多数文字处理、桌面发布、打印等。例如,2100 x 1500 @ 300 dpi = 打印的7" x 5"...
在您的应用程序中,您还可以缩小它或打印它:缩小“添加”分辨率,因此图像变得更清晰。放大使图像模糊或模糊。
我不得不依赖这种技术,因为这是从.Net图表控件获取高分辨率图表以进行打印或保存的最一致的方法...这是一种经典的欺骗,但它有效 :)
例如:
private void cmdHidden_Click(object sender, EventArgs e) {
    System.Windows.Forms.DataVisualization.Charting.Title chtTitle =
        new System.Windows.Forms.DataVisualization.Charting.Title();
    System.Drawing.Font chtFont = new System.Drawing.Font("Arial", 42);
    string[] seriesArray = { "A", "B", "C" };
    int[] pointsArray = { 1, 7, 4 };

    chart1.Visible = false;
    chart1.Width = 2100;
    chart1.Height = 1500;
    chart1.Palette = System.Windows.Forms.DataVisualization.Charting.ChartColorPalette.Bright;

    chtTitle.Font = chtFont;
    chtTitle.Text = "Demographics Comparison";
    chart1.Titles.Add(chtTitle);

    chart1.Series.Clear();

    // populate chart    
    for (int i = 0; i < seriesArray.Length; i++) {
        Series series = chart1.Series.Add(seriesArray[i]);
        series.Label = seriesArray[i].ToString();
        series.Font = new System.Drawing.Font("Arial", 24);
        series.ShadowOffset = 5;
        series.Points.Add(pointsArray[i]);
    }

    // save from the chart object itself
    chart1.SaveImage(@"C:\Temp\HiddenChart.png", ChartImageFormat.Png);

    // save to a bitmap
    Bitmap bmp = new Bitmap(2100, 1500);
    chart1.DrawToBitmap(bmp, new Rectangle(0, 0, 2100, 1500));
    bmp.Save(@"C:\Temp\HiddenChart2.png");
}

您可以通过序列化来克隆图表,如此处所述:https://dev59.com/NHTYa4cB1Zd3GeqP0ewD - flodis

3

这是我创建的一个类,用于制作更大的图表、保存它并恢复图表。这对我的目的非常有效。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OfficeOpenXml.Drawing;
using OfficeOpenXml.Drawing.Chart;
using System.Drawing.Imaging;
using System.Windows.Forms.DataVisualization.Charting;
using System.Windows.Forms;

namespace Simple_Grapher
{
    class saveQualityChartImage
    {
        Chart theChart;
        System.Drawing.Font oldFont1 = new System.Drawing.Font("Trebuchet MS", 35F, System.Drawing.FontStyle.Bold);
        System.Drawing.Font oldFont2 = new System.Drawing.Font("Trebuchet MS", 15F, System.Drawing.FontStyle.Bold);
        System.Drawing.Font oldFont3 = new System.Drawing.Font("Trebuchet MS", 35F, System.Drawing.FontStyle.Bold);
        System.Drawing.Font oldLegendFont = new System.Drawing.Font("Trebuchet MS", 35F, System.Drawing.FontStyle.Bold);

        int oldLineWidth1;
        int oldLineWidth2;
        int oldLineWidth3;
        int oldLineWidth4;

        int oldWidth;
        int oldHeight;
        public saveQualityChartImage(Chart inputChart)
        {
            if (!(inputChart.Series.Count > 0))
            {
                return;
            }
            theChart = inputChart;
            if (inputChart.Titles.Count > 0)
            {
                oldFont1 = inputChart.Titles[0].Font;
            }
            oldFont2 = inputChart.ChartAreas[0].AxisX.LabelStyle.Font;
            oldFont3 = inputChart.ChartAreas[0].AxisX.TitleFont;
            if (theChart.Legends.Count > 0)
            {
                oldLegendFont = theChart.Legends["Legend"].Font;
            }
            oldLineWidth1 = theChart.ChartAreas[0].AxisX.LineWidth;
            oldLineWidth2 = theChart.ChartAreas[0].AxisX.MajorTickMark.LineWidth;
            oldLineWidth3 = theChart.Series[0].BorderWidth;
            oldLineWidth4 = theChart.ChartAreas[0].AxisY.MajorGrid.LineWidth;
            oldWidth = theChart.Width;
            oldHeight = theChart.Height;

            saveimage();
        }

        public void saveimage()
        {
            theChart.Visible = false;
            System.Drawing.Font chtFont = new System.Drawing.Font("Trebuchet MS", 35F, System.Drawing.FontStyle.Bold);
            System.Drawing.Font smallFont = new System.Drawing.Font("Trebuchet MS", 15F, System.Drawing.FontStyle.Bold);
            if (theChart.Titles.Count > 0)
            {
                theChart.Titles[0].Font = chtFont;
            }

            theChart.ChartAreas[0].AxisX.TitleFont = chtFont;
            theChart.ChartAreas[0].AxisX.LineWidth = 3;
            theChart.ChartAreas[0].AxisX.MajorGrid.LineWidth = 3;
            theChart.ChartAreas[0].AxisX.LabelStyle.Font = smallFont;
            theChart.ChartAreas[0].AxisX.MajorTickMark.LineWidth = 3;

            theChart.ChartAreas[0].AxisY.TitleFont = chtFont;
            theChart.ChartAreas[0].AxisY.LineWidth = 3;
            theChart.ChartAreas[0].AxisY.MajorGrid.LineWidth = 3;
            theChart.ChartAreas[0].AxisY.LabelStyle.Font = smallFont;
            theChart.ChartAreas[0].AxisY.MajorTickMark.LineWidth = 3;
            if (theChart.Legends.Count > 0)
            {
                theChart.Legends["Legend"].Font = smallFont;
            }


            foreach (Series series in theChart.Series)
            {
                series.BorderWidth = 3;

            }

            theChart.Width = 1800;
            theChart.Height = 1200;

            SaveFileDialog save = new SaveFileDialog();
            save.DefaultExt = ".png";
            if (save.ShowDialog() == DialogResult.OK)
            {
                theChart.SaveImage(save.FileName, ChartImageFormat.Png);
            }
            resetOldValues();

        }

        private void resetOldValues()
        {
            if (theChart.Titles.Count > 0)
            {
                theChart.Titles[0].Font = oldFont1;
            }

            theChart.ChartAreas[0].AxisX.TitleFont = oldFont3;
            theChart.ChartAreas[0].AxisX.LineWidth = oldLineWidth1;
            theChart.ChartAreas[0].AxisX.MajorGrid.LineWidth = oldLineWidth4;
            theChart.ChartAreas[0].AxisX.LabelStyle.Font = oldFont2;
            theChart.ChartAreas[0].AxisX.MajorTickMark.LineWidth = oldLineWidth2;

            theChart.ChartAreas[0].AxisY.TitleFont = oldFont3;
            theChart.ChartAreas[0].AxisY.LineWidth = oldLineWidth1;
            theChart.ChartAreas[0].AxisY.MajorGrid.LineWidth = oldLineWidth4;
            theChart.ChartAreas[0].AxisY.LabelStyle.Font = oldFont2;
            theChart.ChartAreas[0].AxisY.MajorTickMark.LineWidth = oldLineWidth2;
            if (theChart.Legends.Count > 0)
            {
                theChart.Legends["Legend"].Font = oldLegendFont;
            }



            foreach (Series series in theChart.Series)
            {
                series.BorderWidth = oldLineWidth3;

            }

            theChart.Width = oldWidth;
            theChart.Height = oldHeight;
            theChart.Visible = true;   
        }  
    }
}

1
尝试设置 chart2.RenderTransform = new ScaleTransform(10,10) 并保存。这也应该使您的线条变粗。

0
我要将这个作为一个类添加进来,以便将图表保存为图片,因为我在这里找到的大部分示例都是使用System.Windows.Forms。而我使用的是System.Web.UI.DataVisualization.Charting。这两者之间有一些细微的差别,如果你试图将这个页面上的示例适应到Web服务器上,可能会出现错误。此外,很多其他的SO问题/示例并没有使用IEnumerable数据源。
这里的数据源只是一个普通的DataTable,返回的是AsEnumerable()(例如:return dt.AsEnumerable();)。
标题和图例也被添加到了保存的图片中。
这段代码从一个数据源生成了两张图片。一个是压力图表,另一个是温度图表。下面的压力图表就是这段代码的实际输出。
  public static void ChartToImage(Certification.Chart chartData, string hashId, string orderId, string chartNo, string multiChart = "0")
    {
        string filepath = System.Web.Hosting.HostingEnvironment.MapPath("~/docs/");
        string fileNamePress = filepath + chartData.HashId + "p.png";
        string fileNameTemp = filepath + chartData.HashId + "t.png";

        System.Web.UI.DataVisualization.Charting.Chart chart1 = new System.Web.UI.DataVisualization.Charting.Chart();

        System.Web.UI.DataVisualization.Charting.Title cht1Title = new
        System.Web.UI.DataVisualization.Charting.Title();
        System.Drawing.Font cht1Font = new System.Drawing.Font("Arial", 18);


        System.Web.UI.DataVisualization.Charting.Legend cht1Legend = new
        System.Web.UI.DataVisualization.Charting.Legend();
        System.Drawing.Font cht1LegendFont = new System.Drawing.Font("Arial", 18);

        System.Collections.IEnumerable enumerableTable = ChartDAL.ChartIEList(hashId);

        System.DateTime x = new System.DateTime(2008, 11, 21);

        var chartArea1 = new System.Web.UI.DataVisualization.Charting.ChartArea();
        chart1.ChartAreas.Add(chartArea1);
        chart1.DataSource = enumerableTable;
        
        chart1.Series.Add("Series1");
        chart1.Series["Series1"].ChartType = SeriesChartType.Spline;
        chart1.Series["Series1"].XValueType = ChartValueType.Time;
        chart1.Series["Series1"].Points.AddXY(x.ToUniversalTime(), "tstamp");
        chart1.Series["Series1"].XValueMember = "tstamp";
        chart1.Series["Series1"].YValueMembers = "pressure";
        chart1.Series["Series1"].IsValueShownAsLabel = false;
        chart1.Series["Series1"].Name = "PSI"; // Normally PSI. In the future, pull pressure testing unit from enumerableTable;


        cht1Title.Font = cht1Font;
        cht1Title.Text = "Pressure Chart"; // In future, pull job number/chart number from database;
        chart1.Titles.Add(cht1Title);

        cht1Legend.Font = cht1Font;            
        chart1.Legends.Add(cht1Legend); // chart1.Series["Series1"].Name;

        chart1.Width = 900;
        chart1.Height = 400;
        chart1.DataBind();
        
        chart1.SaveImage(fileNamePress, ChartImageFormat.Png);

        System.Web.UI.DataVisualization.Charting.Chart chart2 = new System.Web.UI.DataVisualization.Charting.Chart();

        System.Web.UI.DataVisualization.Charting.Title cht2Title = new
        System.Web.UI.DataVisualization.Charting.Title();
        System.Drawing.Font cht2Font = new System.Drawing.Font("Arial", 18);

        System.Web.UI.DataVisualization.Charting.Legend cht2Legend = new
        System.Web.UI.DataVisualization.Charting.Legend();
        System.Drawing.Font cht2LegendFont = new System.Drawing.Font("Arial", 18);

        var chartArea2 = new System.Web.UI.DataVisualization.Charting.ChartArea();
        chart2.ChartAreas.Add(chartArea2);
        chart2.DataSource = enumerableTable;

        chart2.Series.Add("Series1");
        chart2.Series["Series1"].ChartType = SeriesChartType.Spline;
        chart2.Series["Series1"].XValueType = ChartValueType.Time;
        chart2.Series["Series1"].Points.AddXY(x.ToUniversalTime(), "tstamp");
        chart2.Series["Series1"].XValueMember = "tstamp";
        chart2.Series["Series1"].YValueMembers = "temperature";
        chart2.Series["Series1"].IsValueShownAsLabel = false;
        chart2.Series["Series1"].Name = "Celsius"; // Normally Celsius. In the future, pull temperature testing unit from enumerableTable;

        cht2Title.Font = cht2Font;
        cht2Title.Text = "Temperature Chart"; // In future, pull job number/chart number from database;
        chart2.Titles.Add(cht2Title);

        cht2Legend.Font = cht2Font;            
        chart2.Legends.Add(cht2Legend); // chart2.Series["Series1"].Name;

        chart2.Width = 900;
        chart2.Height = 400;
        chart2.DataBind();

        chart1.SaveImage(fileNamePress, ChartImageFormat.Png);
        chart2.SaveImage(fileNameTemp, ChartImageFormat.Png);


    }   

enter image description here


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接