I have to generate dynamic graphs on the fly, save it as a PNG image format (Transparent background) to be embedded on to a PDF.
The problem is, the graph will not be displayed on a control in the page (without a chart control in the WebForm) and should be generated from an underlying information and should be embedded while creating the PDF.
The libraries for the PDFs and PDF generation is all in place.
I would like to know how to generate a dynamic graph (Bar graph, Pie Graph) 3D or Simple graph without a chart control in place and be able to save it as an image with transparent background (.PNG).
The reason being, the PDF template has numerous layer shading, hence the background around the graph image should be transparent, something similar to the below image.
I have tried generating a dynamic bar graph similar to the example in the below link but the Image doesn't look promising
https://2leggedspider.wordpress.com/2004/11/21/generating-a-dynamic-bar-graph-using-aspnet-and-c/
Any help regarding the functionality is deeply appreciated. Thank you in advance.
Update: Wednesday 16th March 2016
With TaW's answer and updates I have been able to draw the required graph and below is the update with answer to the same question I asked
Add references to System.Windows.Forms and System.Windows.Forms.DataVisualization
Add below namespaces
using System.Drawing;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;
And below method would give you the Pie Chart with smooth edges as shown in the picture
void Create3DPieChart()
{
/* Utilize the Chart class available in System.Windows.Forms.DataVisualization.Charting */
Chart chart = new Chart();
/* Add a chart area to the chart */
ChartArea CA = chart.ChartAreas.Add("A1");
/* Add data series to the chart and specify the type of Series */
Series S1 = chart.Series.Add("S1");
S1.ChartType = SeriesChartType.Pie;
/* Assign points for the Series */
S1.Points.AddXY(1, 17);
S1.Points.AddXY(2, 27);
S1.Points.AddXY(3, 7);
S1.Points.AddXY(4, 49);
/* Set chart color and other settings as required */
chart.BackColor = Color.Transparent;
CA.BackColor = chart.BackColor;
CA.Area3DStyle.Enable3D = true;
S1.Points[2]["Exploded"] = "true";
/*Assign AntiAliasing to Graphics style for smooth edges*/
chart.AntiAliasing = AntiAliasingStyles.Graphics;
/* Set the image path and save the image as PNG format*/
string imageNameAndPath = string.Concat(Application.StartupPath.Remove(Application.StartupPath.IndexOf("\\bin\\Debug")),
"/TempImages/Image", DateTime.Now.ToString("ddMMyyyyhhmmss") + ".png");
chart.SaveImage(imageNameAndPath, ChartImageFormat.Png);
}
TaW. Please correct me if I'm wrong.
Unfortunately the chart won't draw any transparency directly, so we need to workaround..
If you want to create a PNG with transparent background here is what you can do:
chart1.BackColor = Color.Fuchsia;
chart1.ChartAreas[0].BackColor = chart1.BackColor;
Bitmap bmp = new Bitmap( chart1.ClientSize.Width, chart1.ClientSize.Height);
chart1.AntiAliasing = AntiAliasingStyles.Graphics;
chart1.DrawToBitmap(bmp, chart1.ClientRectangle);
bmp.MakeTransparent(chart1.BackColor);
bmp.Save(yourFileName, ImageFormat.Png);
First we set some areas in the chart to a unique color; if you use fuchsia in your chart (yuck!), pick some other color.
Then we create a Bitmap to hold the image.
Now we turn anti-aliasing off for the text; this help to avoid funny colors when we turn the background pixels to tranparent.
Now we tell the chart control to draw itself into our bitmap.
Finally we make all pixels transparent that have our special color.
Now we can save to disk..
You may want to look into setting the dpi resolution and the chart size to make the result look nice in your pdf!
Update:
If you want to create the image without acutally showing a Chart control, there is no real problem, either. In fact you can even create a Chart image in a console application, if you include all necessary namespaces etc..
All you need to do is create the Chart in code and set up all necessary properties.
Here is a minimal example:
Chart chart = new Chart();
ChartArea CA = chart.ChartAreas.Add("A1");
Series S1 = chart.Series.Add("S1");
S1.ChartType = SeriesChartType.Pie;
S1.Points.AddXY(1, 17);
S1.Points.AddXY(2, 27);
S1.Points.AddXY(3, 7);
S1.Points.AddXY(4, 49);
chart.BackColor = Color.Fuchsia;
CA.BackColor = chart.BackColor;
CA.Area3DStyle.Enable3D = true;
S1.Points[2]["Exploded"] = "true";
Bitmap bmp = new Bitmap(chart.Width, chart.Height);
chart.AntiAliasing = AntiAliasingStyles.None;
chart.DrawToBitmap(bmp, chart.ClientRectangle);
bmp.MakeTransparent(chart.BackColor);
bmp.Save(yourFileName, ImageFormat.Png);
Related
I have a C# 4.7 WinForms application with line chart. I want to save chart image with very large resolution e.g 10000x2000. Here is what I have archived:
Form1.Width = 3860; //my screen width resolution - maximum allowed
Form1.Height = 1080; //my screen height resolution - maximum allowed
chart1.Dock = DockStyle.Fill;
chart1.SaveImage(saveFile.FileName, ChartImageFormat.Jpeg);
That code saves jpeg image with 3860x1080 resolution and i can zoom in points I need. But it is not enough and I want to enlarge my form or chart to
get an image like 10000x2000, VS says it cannot be larger than my screen.
I have a lot of data on this chart, so bigger form provides me with more data on a chart. Picture is required for other people to see the maximum info.
How can I do it?
This is quite simple.
All you need to do is create the Chart in code without displaying it on screen.
Now you can size it as needed..:
Chart bigChart = new Chart();
bigChart.ChartAreas.Add("ca");
Series s1 = bigChart.Series.Add("s1");
s1.BorderWidth = 5;
s1.ChartType = SeriesChartType.Line;
// testdata
Random rnd = new Random(8);
for (int i = 0; i < 111; i++)
{
s1.Points.AddXY(rnd.Next(123) + i, rnd.Next(12 * i)) ;
}
bigChart.Size = new Size(10000, 8000);
bigChart.SaveImage(filename, ChartImageFormat.Png);
A few notes:
You may want to add a Legend as well, as the dynamically created Chart has none of the default elements..
If you want to you can use a chart you have, serialize its content to a file (or stream) and then load (deserialize) it into the big chart..
The automatic smartness of MSChart tends to hit some limit when the sizes grow a lot; so brace yourself for tweaking some settings for line width, Fonts etc..
You also may want to load the saved image and set the dpi to a bigger values than the default, which is the screen resolution..
Final remark: Sometimes it is better to save the chart as a vector format; these are also provided in the SaveImage method.
Update: Maybe you want to combine vector and pixel formats as in Jimi's last comments.
You may want to study this post which discusses a few general options.
I was wondering how PowerPoint slides can be automatically annotated using digital ink in .NET (using c#). Currently, I'm doing the same thing using free-form shapes, which is straightforward but has some issues. When selecting Office.MsoEditingType.msoEditingAuto as an editing type, the free-forms are smooth, but when constructing them and then converting into a shape (when consisting of more than a couple of points) takes a very long time (the following method would take ca 5s!)
PowerPoint.Shape Shape = builder.ConvertToShape();
When using Office.MsoEditingType.msoEditingCorner, the shape is generated much quicker, but the resulting shapes are jagged (surprise!).
I found the following code sample for doing the same using digital ink:
DrawingAttributes drawingAttributes1 = new DrawingAttributes();
drawingAttributes1.Color = Colors.Green;
StylusPoint stylusPoint1 = new StylusPoint(100, 100);
StylusPoint stylusPoint2 = new StylusPoint(100, 200);
StylusPoint stylusPoint3 = new StylusPoint(200, 200);
StylusPoint stylusPoint4 = new StylusPoint(200, 100);
StylusPoint stylusPoint5 = new StylusPoint(100, 100);
StylusPointCollection points = new StylusPointCollection(
new StylusPoint[] { stylusPoint1, stylusPoint2, stylusPoint3,
stylusPoint4, stylusPoint5 });
Stroke newStroke = new Stroke(points, drawingAttributes1);
InkPresenter inkPres = new InkPresenter();
inkPres.Strokes.Add(newStroke);
However, not being a PowerPoint Add-in expert (hardly even a beginner, actually), I don't know how to attach the inkpresenter to the current slide. Ideally, a new inkpresenter would be created & kept per slide (so I don't have to worry about re-drawing on each slide navigation)
I understood it's possible to create an ink canvas using the designer, and then drawing on that, but would that canvas then be attached to the entire presentation or just the current slide? And would it allow users to draw on the canvas (which is not the goal; drawing would be done automatically)?
I spent quite some time looking for relevant code samples, but none of them seemed to do what I am intending. For instance, as mentioned, I'm not planning to allow users to draw on the slide, but automatically annotating the slide.
Thanks,
William
How can I create a background for a chart that looks like this?
It's got different background colors at certain % levels that correspond to the status. All I see in ChartArea is BackColor, BackSecondaryColor, and BackGradientStyle which won't do this. This image was taken from an SSRS report and I am trying to recreate it using C# and the Microsoft charting library. I am pretty sure SSRS uses the same library so it should be possible - I just don't know how.
You can achieve this by using StripLine.
// Create the stripline for 'gold status'
StripLine sline = new StripLine();
sline.IntervalOffset = 0.6;
sline.StripWidth = 0.25;
sline.Text = "Gold Status";
sline.Interval = 0.0; // this ensures it will not repeat like normal strip lines
sline.BackColor = Color.Yellow;
myChart.AxisY.StripLines.Add(sline);
repeat the process for your silver and platinum strip lines.
I'm using Steema TeeChart v4.1.2010.11303. I want to export a chart to a PNG image with a transparent background.
The resulting image has "distorted" or bold text in the left and bottom axis and in the header. It looks like being rendered with a raster font with a too low resolution. The legend on the right on the other hand looks fine:
The following sample code can be used to reproduce the problem:
TChart tChart = new TChart();
tChart.Aspect.View3D = false;
tChart.Panel.Brush.Gradient.Visible = false;
// Make the background of the chart transparent.
tChart.Panel.Transparent = true;
Steema.TeeChart.Styles.Bar series1 = new Steema.TeeChart.Styles.Bar( tChart.Chart );
series1.FillSampleValues();
tChart.Draw();
tChart.Graphics3D.BufferStyle = Steema.TeeChart.Drawing.BufferStyle.None;
using ( System.IO.Stream stream = new System.IO.MemoryStream() )
{
tChart.Export.Image.PNG.Width = m_PictureBox.Width;
tChart.Export.Image.PNG.Height = m_PictureBox.Height;
tChart.Export.Image.PNG.Save( stream );
// Show the bitmap in a Windows Forms PictureBox.
// Alternatively, it can also be saved in a file, which makes no difference.
PictureBox.Image = new Bitmap( stream );
}
When switching off the transparency with tChart.Panel.Transparent = false;, all text looks fine. However, I need a transparent background.
Is this a bug in TeeChart or am I missing something?
It is a know behavior for us and we haven't found a good solution for this problem, for the moment. If we will find a solution that we consider correct or we will arrive an interesting conclusion about problem of png export, we will inform you immediatly.
Thanks.
Best Regard,
Sandra Pazos
I am using some custom controls one of which is a tooltip controller that can display images, so I am using th ebelow code to instantiate it:
Image newImage = Image.FromFile(imagePath);
e.ToolTipImage = newImage;
obviously could inline it but just testing at the moment. The trouble is the image is sometimes the wrong size, is there a way to set the display size. The only way I can currently see is editing the image using GDI+ or something like that. Seems like a lot of extra processing when I am only wanting to adjust display size not affect the actual image.
Once you have an image object loaded from its source, the Height and Width (and Size, and all ancillary properties) are read-only. Therefore, you are stuck with GDI+ methods for resizing it in RAM and then displaying it accordingly.
There are a lot of approaches you can take, but if you were to encapsulate that out to a library which you could reuse should this problem occur again, you'll be set to go. This isn't exactly optimized (IE, may have some bugs), but should give you an idea of how to approach it:
Image newImage = Image.FromFile(myFilePath);
Size outputSize = new Size(200, 200);
Bitmap backgroundBitmap = new Bitmap(outputSize.Width, outputSize.Height);
using (Bitmap tempBitmap = new Bitmap(newImage))
{
using (Graphics g = Graphics.FromImage(backgroundBitmap))
{
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
// Get the set of points that determine our rectangle for resizing.
Point[] corners = {
new Point(0, 0),
new Point(backgroundBitmap.Width, 0),
new Point(0, backgroundBitmap.Height)
};
g.DrawImage(tempBitmap, corners);
}
}
this.BackgroundImage = backgroundBitmap;
I did test this, and it worked. (It created a 200x200 resized version of one of my desktop wallpapers, then set that as the background image of the main form in a scratch WinForms project. You'll need using statements for System.Drawing and System.Drawing.Drawing2D.
In Winforms, if you contain the image inside a PictureBox control, the PictureBox control can be set to zoom to a particular height/width, and the image should conform.
At least that's what happened in my Head First C# book when I did the exercise.