exporting plot to png.

Oystein Bjorke fa 10 anys 0
This discussion was imported from CodePlex

vdepa wrote at 2012-03-02 12:13:

 

Hi all,

Can anyone please share  code for exporting plot to png from the step onwards.

It's very urgent to me.

Please help.

 

 

 


ffiala wrote at 2012-03-02 22:40:

This is my file "BitmapRenderContext.cs" which is originally copied from SvgRenderContext.cs substituting the calls to svg writer through calls to Graphic class. This Class returns a Bitmap.

// --------------------------------------------------------------------------------------------------------------------
// 
//   http://oxyplot.codeplex.com, license: Ms-PL
// 
// --------------------------------------------------------------------------------------------------------------------

namespace OxyPlot
{
    using System;
    using System.Collections.Generic;
    using System.Drawing;
    using System.Drawing.Drawing2D;
    using System.Drawing.Text;

    /// 
    /// The Bitmap render context.
    /// 
    public class BitmapRenderContext : RenderContextBase, IDisposable
    {
        #region Constants and Fields

        public Bitmap objBmpImage;
        Graphics objGraphics;

        #endregion

        #region Constructors and Destructors

        /// 
        /// Initializes a new instance of the  class.
        /// 
        /// <param name="s" />
        /// The s.
        /// 
        /// <param name="width" />
        /// The width.
        /// 
        /// <param name="height" />
        /// The height.
        /// 
        /// <param name="isDocument" />
        /// The is document.
        /// 
        public BitmapRenderContext(double width, double height)
        {
            this.Width = width;
            this.Height = height;
            this.PaintBackground = true;
            objBmpImage = new Bitmap((int)width, (int)height);
            objGraphics = Graphics.FromImage(objBmpImage);
            objGraphics.Clear(Color.White);
            objGraphics.SmoothingMode = SmoothingMode.AntiAlias;
            objGraphics.TextRenderingHint = TextRenderingHint.AntiAlias;
        }

#if !METRO

        /// 
        /// Initializes a new instance of the  class.
        /// 
        /// <param name="path" />
        /// The path.
        /// 
        /// <param name="width" />
        /// The width.
        /// 
        /// <param name="height" />
        /// The height.
        /// 
        public BitmapRenderContext(string path, double width, double height)
        {
        }

#endif

        #endregion

        #region Public Methods

        /// 
        /// The close.
        /// 
        public void Close()
        {
        }

        /// 
        /// The complete.
        /// 
        public void Complete()
        {
        }

        /// 
        /// The dispose.
        /// 
        public void Dispose()
        {
            objBmpImage.Dispose();
        }

        /// 
        /// The draw ellipse.
        /// 
        /// <param name="rect" />
        /// The rect.
        /// 
        /// <param name="fill" />
        /// The fill.
        /// 
        /// <param name="stroke" />
        /// The stroke.
        /// 
        /// <param name="thickness" />
        /// The thickness.
        /// 
        public override void DrawEllipse(OxyRect rect, OxyColor fill, OxyColor stroke, double thickness)
        {
            Pen pen = stroke == null ? null : new Pen(Color.FromArgb(stroke.A, stroke.R, stroke.G, stroke.B), (int)thickness);
            Rectangle grect = new Rectangle((int)rect.Left, (int)rect.Top, (int)rect.Width, (int)rect.Height);
            SolidBrush brush = fill == null ? null : new SolidBrush(Color.FromArgb(fill.A, fill.R, fill.G, fill.B));
            if (pen != null) objGraphics.DrawEllipse(pen, grect);
            if (brush != null) objGraphics.FillEllipse(brush, grect);
        }

        /// 
        /// The draw line.
        /// 
        /// <param name="points" />
        /// The points.
        /// 
        /// <param name="stroke" />
        /// The stroke.
        /// 
        /// <param name="thickness" />
        /// The thickness.
        /// 
        /// <param name="dashArray" />
        /// The dash array.
        /// 
        /// <param name="lineJoin" />
        /// The line join.
        /// 
        /// <param name="aliased" />
        /// The aliased.
        /// 
        public override void DrawLine(
            IList points, 
            OxyColor stroke, 
            double thickness, 
            double[] dashArray, 
            OxyPenLineJoin lineJoin, 
            bool aliased)
        {
            Point[] Gpoints = new Point[points.Count];
            for (int i=0; i
        /// The draw polygon.
        /// 
        /// <param name="points" />
        /// The points.
        /// 
        /// <param name="fill" />
        /// The fill.
        /// 
        /// <param name="stroke" />
        /// The stroke.
        /// 
        /// <param name="thickness" />
        /// The thickness.
        /// 
        /// <param name="dashArray" />
        /// The dash array.
        /// 
        /// <param name="lineJoin" />
        /// The line join.
        /// 
        /// <param name="aliased" />
        /// The aliased.
        /// 
        public override void DrawPolygon(
            IList points, 
            OxyColor fill, 
            OxyColor stroke, 
            double thickness, 
            double[] dashArray, 
            OxyPenLineJoin lineJoin, 
            bool aliased)
        {
            Point[] Gpoints = new Point[points.Count];
            for (int i = 0; i < points.Count; i++)
            {
                Gpoints[i].X = (int)points[i].X;
                Gpoints[i].Y = (int)points[i].Y;
            }
            Pen pen = stroke == null ? null : new Pen(Color.FromArgb(stroke.A, stroke.R, stroke.G, stroke.B), (int)thickness);
            if (pen != null) objGraphics.DrawPolygon(pen, Gpoints);
            SolidBrush brush = fill == null ? null : new SolidBrush(Color.FromArgb(fill.A, fill.R, fill.G, fill.B));
            if (brush != null) objGraphics.FillPolygon(brush, Gpoints);
        }

        /// 
        /// The draw rectangle.
        /// 
        /// <param name="rect" />
        /// The rect.
        /// 
        /// <param name="fill" />
        /// The fill.
        /// 
        /// <param name="stroke" />
        /// The stroke.
        /// 
        /// <param name="thickness" />
        /// The thickness.
        /// 
        public override void DrawRectangle(OxyRect rect, OxyColor fill, OxyColor stroke, double thickness)
        {
            Pen pen = stroke==null ? null : new Pen(Color.FromArgb(stroke.A,stroke.R,stroke.G,stroke.B), (int)thickness);
            Rectangle grect = new Rectangle((int)rect.Left, (int)rect.Top, (int)rect.Width, (int)rect.Height);
            SolidBrush brush = fill == null ? null : new SolidBrush(Color.FromArgb(fill.A, fill.R, fill.G, fill.B));
            if (pen!=null) objGraphics.DrawRectangle(pen, grect);
            if (brush != null) objGraphics.FillRectangle(brush, grect);
        }

        /// 
        /// The draw text.
        /// 
        /// <param name="p" />
        /// The p.
        /// 
        /// <param name="text" />
        /// The text.
        /// 
        /// <param name="c" />
        /// The c.
        /// 
        /// <param name="fontFamily" />
        /// The font family.
        /// 
        /// <param name="fontSize" />
        /// The font size.
        /// 
        /// <param name="fontWeight" />
        /// The font weight.
        /// 
        /// <param name="rotate" />
        /// The rotate.
        /// 
        /// <param name="halign" />
        /// The halign.
        /// 
        /// <param name="valign" />
        /// The valign.
        /// 
        /// <param name="maxSize" />
        /// Max size of the text (clipping rectangle).
        /// 
        public override void DrawText(
            ScreenPoint p, 
            string text, 
            OxyColor c, 
            string fontFamily, 
            double fontSize, 
            double fontWeight, 
            double rotate, 
            HorizontalTextAlign halign, 
            VerticalTextAlign valign, 
            OxySize? maxSize)
        {
            double SizeCorrectingFactor = 0.8;
            double VerticalCorrectingFactor = fontSize * 0.3;
            Point Gp = new Point((int)(p.X-VerticalCorrectingFactor), (int)(p.Y));
            Font font = new Font(fontFamily,(float)(fontSize*SizeCorrectingFactor), FontStyle.Regular);
            SolidBrush brush = c == null ? null : new SolidBrush(Color.FromArgb(c.A, c.R, c.G, c.B));
            StringFormat stringFormat = new StringFormat();
            /* dont know how to vertically align text, so this setting is skipped */
            if (brush != null)
            {
                if (Math.Abs(rotate) < 0.1)
                {
                    switch (halign)
                    {
                        case HorizontalTextAlign.Center:
                            stringFormat.Alignment = StringAlignment.Center;
                            break;
                        case HorizontalTextAlign.Left:
                            stringFormat.Alignment = StringAlignment.Near;
                            break;
                        case HorizontalTextAlign.Right:
                            stringFormat.Alignment = StringAlignment.Far;
                            break;
                    }
                    objGraphics.DrawString(text, font, brush, Gp, stringFormat);
                }
                else
                {
                    switch (halign)
                    {
                        case HorizontalTextAlign.Center:
                            stringFormat.Alignment = StringAlignment.Center;
                            break;
                        case HorizontalTextAlign.Left:
                            stringFormat.Alignment = StringAlignment.Near;
                            break;
                        case HorizontalTextAlign.Right:
                            stringFormat.Alignment = StringAlignment.Far;
                            break;
                    }
                    stringFormat.Alignment = StringAlignment.Far;
                    SizeF size = objGraphics.MeasureString(text, font);
                    Bitmap tempImage = new Bitmap((int)(size.Height * 1.2), (int)(size.Width * 1.2));
                    Graphics tempGraphics = Graphics.FromImage(tempImage);
                    tempGraphics.TextRenderingHint = TextRenderingHint.AntiAlias;
                    tempGraphics.SmoothingMode = SmoothingMode.AntiAlias;

                    Rectangle rect = new Rectangle((int)tempGraphics.VisibleClipBounds.X, (int)tempGraphics.VisibleClipBounds.Y, (int)tempGraphics.VisibleClipBounds.Width, (int)tempGraphics.VisibleClipBounds.Height);
                    tempGraphics.TranslateTransform(0, 0);
                    tempGraphics.RotateTransform(270);
                    tempGraphics.DrawString(text, font, brush, new PointF(0, 0), stringFormat);
                    objGraphics.DrawImage(tempImage, Gp);

                    objGraphics.DrawImage(tempImage, Gp);
                    tempGraphics.Dispose();
                    tempImage.Dispose();
                }
            }
        }
        /// 
        /// The flush.
        /// 
        public void Flush()
        {
            objGraphics.Flush();
        }

        /// 
        /// The measure text.
        /// 
        /// <param name="text" />
        /// The text.
        /// 
        /// <param name="fontFamily" />
        /// The font family.
        /// 
        /// <param name="fontSize" />
        /// The font size.
        /// 
        /// <param name="fontWeight" />
        /// The font weight.
        /// 
        /// 
        /// 
        public override OxySize MeasureText(string text, string fontFamily, double fontSize, double fontWeight)
        {
            if (string.IsNullOrEmpty(text))
            {
                return OxySize.Empty;
            }

            // todo: should improve text measuring, currently using p/invoke on GDI32
            // is it better to use winforms or wpf text measuring?
            return Gdi32.MeasureString(fontFamily, (int)fontSize, (int)fontWeight, text);
        }

        #endregion
    }
}

In PlotModel.cs the following method is added:

        /// 
        /// Create a Drawing 
        /// 
        /// <param name="width" />
        /// The width. 
        /// 
        /// <param name="height" />
        /// The height. 
        /// 
        /// <param name="isDocument" />
        /// if set to true [is document]. 
        /// 
        /// 
        /// The to svg. 
        /// 
        public Bitmap ToBitmap(double width, double height)
        {
            var bmrc = new BitmapRenderContext(width, height);
            this.Update();
            this.Render(bmrc);
            bmrc.Complete();
            bmrc.Flush();
            return (bmrc.objBmpImage);
        }

To send the image to the client:

Response.Clear();
Response.ContentType = "image/png";
Bitmap bmp = plot.GetBitmap(800, 500);
bmp.Save(Response.OutputStream, ImageFormat.Png);

In this version only solid lines are rendered.
Franz


vdepa wrote at 2012-03-05 08:13:

Franz,

Thanks a lot for the code.


vdepa wrote at 2012-03-06 19:06:

Hi fmoses,

 I am unable to save the png. The above code is not working at the draw line.

 I writting the below sample code for testing. I have used plot model and plot as in the example

 Can you please correct the mistake in the below code. XAML Code:

 C# Code :

 using OxyPlot;

 using OxyPlot.Wpf;

 try

 {

 InitializeComponent(); Model = TwoLineSeries();

 DataContext = this; Plot objPlot = this.plot1;

var path = GetFilename(".png files|*.png", ".png");

if (path != null) { objPlot.SaveBitmap(path); } } catch (Exception ex) { string abc = ex.Message.ToString(); }

public static PlotModel TwoLineSeries()

{

var model = new PlotModel();

 OxyPlot.LinearAxis abcd = new OxyPlot.LinearAxis();

abcd.Key = "Hours";

abcd.Position = AxisPosition.Left;

abcd.Title = "Hours";

abcd.MajorGridlineStyle = LineStyle.Solid;

model.Axes.Add(abcd);

 OxyPlot.LinearAxis abc = new OxyPlot.LinearAxis();

 abc.Key = "Men";

 abc.Position = AxisPosition.Bottom;

 abc.Title = "Men"; model.Axes.Add(abc);

var s1 = new OxyPlot.LineSeries("Series 1")

{

Color = OxyColors.SkyBlue, };

 s1.YAxisKey = abcd.Key; for (int i = 0; i < 300; i++)

{

s1.Points.Add(new DataPoint(i, i + 10));

 }

model.LegendPlacement = LegendPlacement.Outside;

model.LegendOrientation = LegendOrientation.Horizontal;

return model;

Please help me.

Thanks & Regards

 vdepa