RadChartView PDF and High Quality Image Export

1 Answer 268 Views
ChartView
George C.
Top achievements
Rank 2
Iron
Veteran
George C. asked on 12 Aug 2021, 10:05 PM

Greetings,

I've tested the image export functionality of RadChartView, however, the output quality isn't quite high, and therefore, it isn't appropriate for printing stuff (I tested JPEG format).

I also searched for PDF output of RadChartView, most implemented methods are all about putting an exported image of RadChartView into a PDF document.

First Question : Is it possible to export a high-quality image of RadChartView? and is it possible to change the background color of the exported image? (as default it exports the image with white background; JPEG)

Second Question : What's the best way to export a RadChartview into a PDF document?

 

Thanks in advance.

 

 

 

 

 

1 Answer, 1 is accepted

Sort by
0
Accepted
Dess | Tech Support Engineer, Principal
Telerik team
answered on 13 Aug 2021, 01:43 PM
Hello, George,

There is not straightforward way to change the quality of the exported image. You can find below the default logic for exporting RadChartView as an image:
        public void ExportToImage(Stream stream, Size size, ImageFormat imageFormat)
        {
            if (!this.IsLoaded)
            {
                this.LoadElementTree();
            }            

            Bitmap bmp = new Bitmap(size.Width, size.Height);
            Graphics graphics = null;
            Graphics fromBitmapGraphics = null;
            Metafile metafile = null;

            bool isMetaFile = imageFormat == ImageFormat.Emf || imageFormat == ImageFormat.Wmf;
            if (isMetaFile)
            {
                fromBitmapGraphics = Graphics.FromImage(bmp);
                metafile = new Metafile(stream, fromBitmapGraphics.GetHdc());
                graphics = Graphics.FromImage(metafile);               
            }
            else
            {
                graphics = Graphics.FromImage(bmp);
            }

            graphics.Clear(Color.White);

            StringFormat titleStringFormat = this.ChartElement.TitleElement.TextParams.CreateStringFormat();
            // Set no trimming - TFS issue id #436542
            titleStringFormat.Trimming = StringTrimming.None;
            SizeF titleSize = graphics.MeasureString(this.Title, this.ChartElement.TitleElement.Font, this.Width, titleStringFormat);

            if (this.ChartElement.TitleElement.TextOrientation == Orientation.Vertical)
            {
                float swap = titleSize.Height;
                titleSize.Height = titleSize.Width;
                titleSize.Width = swap;
            }

            RadRect titleRect = new RadRect(0, 0, titleSize.Width, titleSize.Height);
            RadRect legendRect = new RadRect(0, 0, size.Width, size.Height);
            RadRect chartRect = legendRect;

            titleRect.X += this.chartElement.TitleElement.PositionOffset.Width;
            titleRect.Y += this.chartElement.TitleElement.PositionOffset.Height;

            switch (this.chartElement.TitlePosition)
            {
                case TitlePosition.Top:
                case TitlePosition.Bottom:
                    titleRect.Width = size.Width;
                    break;
                case TitlePosition.Right:
                case TitlePosition.Left:
                    titleRect.Height = size.Height;
                    break;
            }

            chartRect.X += this.View.Margin.Left;
            chartRect.Y += this.View.Margin.Top;
            chartRect.Width -= this.View.Margin.Horizontal;
            chartRect.Height -= this.View.Margin.Vertical;

            if (this.ShowTitle)
            {
                switch (this.ChartElement.TitlePosition)
                {
                    case TitlePosition.Top:
                        legendRect.Y += titleRect.Height;
                        chartRect.Y += titleRect.Height;
                        legendRect.Height -= titleRect.Height;
                        chartRect.Height -= titleRect.Height;
                        break;
                    case TitlePosition.Right:
                        titleRect.X = size.Width - this.ChartElement.TitleElement.Size.Width;
                        titleRect.Height = size.Height;
                        legendRect.Width -= titleRect.Width;
                        chartRect.Width -= titleRect.Width;
                        break;
                    case TitlePosition.Bottom:
                        titleRect.Y = size.Height - this.ChartElement.TitleElement.Size.Height;
                        titleRect.Width = size.Width;
                        legendRect.Height -= titleRect.Height;
                        chartRect.Height -= titleRect.Height;
                        break;
                    case TitlePosition.Left:
                        titleRect.Height = size.Height;
                        legendRect.X += titleRect.Width;
                        chartRect.X += titleRect.Width;
                        legendRect.Width -= titleRect.Width;
                        chartRect.Width -= titleRect.Width;
                        break;
                }
            }

            if (this.ShowLegend)
            {
                switch (this.ChartElement.LegendPosition)
                {
                    case LegendPosition.Right:
                        if (this.ChartElement.TitlePosition == TitlePosition.Right)
                        {
                            legendRect.X = titleRect.X - this.ChartElement.LegendElement.Size.Width;
                        }
                        else
                        {
                            legendRect.X = size.Width - this.ChartElement.LegendElement.Size.Width;
                        }

                        legendRect.Width = this.ChartElement.LegendElement.Size.Width;
                        chartRect.Width -= legendRect.Width;
                        break;
                    case LegendPosition.Bottom:
                        if (this.ChartElement.TitlePosition == TitlePosition.Bottom)
                        {
                            legendRect.Y = titleRect.Y - this.ChartElement.LegendElement.Size.Height;
                        }
                        else
                        {
                            legendRect.Y = size.Height - this.ChartElement.LegendElement.Size.Height;
                        }

                        legendRect.Height = this.ChartElement.LegendElement.Size.Height;
                        chartRect.Height -= legendRect.Height;
                        break;
                    case LegendPosition.Left:
                        legendRect.Width = this.ChartElement.LegendElement.Size.Width;
                        chartRect.X += legendRect.Width;
                        chartRect.Width -= legendRect.Width;
                        break;
                    case LegendPosition.Top:
                        legendRect.Height = this.ChartElement.LegendElement.Size.Height;
                        chartRect.Y += legendRect.Height;
                        chartRect.Height -= legendRect.Height;
                        break;
                    case LegendPosition.Float:
                        legendRect.Width = this.ChartElement.LegendElement.Size.Width;
                        legendRect.Height = this.ChartElement.LegendElement.Size.Height;
                        double xRatio = size.Width / this.Size.Width;
                        double yRatio = size.Height / this.Size.Height;
                        legendRect.X = (this.ChartElement.LegendOffset.X * xRatio) + ((this.ChartElement.TitlePosition == TitlePosition.Left) ? titleRect.Right : 0d);
                        legendRect.Y = (this.ChartElement.LegendOffset.Y * yRatio) + ((this.ChartElement.TitlePosition == TitlePosition.Top) ? titleRect.Bottom : 0f);
                        break;
                }
            }

            this.View.Layout(chartRect);
            this.Area.Renderer.Draw(graphics);

            if (this.ShowLegend)
            {
                float xTransform = (float)legendRect.X - this.ChartElement.LegendElement.ControlBoundingRectangle.X + ((float)legendRect.Width - this.ChartElement.LegendElement.ControlBoundingRectangle.Width) / 2f;
                float yTransform = (float)legendRect.Y - this.ChartElement.LegendElement.ControlBoundingRectangle.Y + ((float)legendRect.Height - this.ChartElement.LegendElement.ControlBoundingRectangle.Height) / 2f;
                graphics.TranslateTransform(xTransform, yTransform);
                this.ChartElement.LegendElement.Paint(new RadGdiGraphics(graphics), this.ChartElement.LegendElement.ControlBoundingRectangle, 0f, new SizeF(1f, 1f), true);
                graphics.ResetTransform();
            }

            RadGdiGraphics radGraphics = new RadGdiGraphics(graphics);

            if (this.ShowTitle)
            {
                radGraphics.DrawString(
                    this.Title, 
                    this.GetTitleDrawRectangle(ChartRenderer.ToRectangleF(titleRect), titleSize, this.ChartElement.TitleElement.TextAlignment),
                    this.ChartElement.TitleElement.Font,
                    this.ChartElement.TitleElement.ForeColor, 
                    titleStringFormat, 
                    this.ChartElement.TitleElement.TextOrientation, 
                    this.ChartElement.TitleElement.FlipText);
            }

            if (isMetaFile)
            {  
                metafile.Dispose();//this will save the metafile to stream
                if (fromBitmapGraphics != null)
                {
                    fromBitmapGraphics.Dispose();
                }

            }
            else
            {
                bmp.Save(stream, imageFormat);
            }

            this.View.Layout();
        }

The CaresianRenderer uses the default DrawPart for each series for drawing: 

        public override void Draw(object context)
        {
            if (renderPass < 2)
            {
                if (this.Area.View.Owner.Control.Site == null)
                {
                    for (int i = 0; i < this.Area.Series.Count; i++)
                    {
                        if (this.Area.Series[i].IsVisible && !this.Area.Series[i].Model.IsArrangeValid)
                        {
                            this.Area.View.Layout(false);
                            renderPass++;
                            break;
                        }
                    }
                }
            }

            base.Draw(context);

            Initialize();

            for (int i = 0; i < this.drawParts.Count; i++)
            {
                this.drawParts[i].Draw();
            }

            this.renderPass = 0;
        }

It is possible to export the chart to an image as it looks by using the well known Control.DrawToBitmap method:

https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.control.drawtobitmap?view=net-5.0 

If you need to export the chart data to a document, e.g. pdf, you can use a RadDocument and insert the exported image into it. Afterwards, you can use the RadRichTextEditor 's export functionality.

I believe that it would be useful for achieving your goal.

Regards,
Dess | Tech Support Engineer, Principal
Progress Telerik

Love the Telerik and Kendo UI products and believe more people should try them? Invite a fellow developer to become a Progress customer and each of you can get a $50 Amazon gift voucher.

Tags
ChartView
Asked by
George C.
Top achievements
Rank 2
Iron
Veteran
Answers by
Dess | Tech Support Engineer, Principal
Telerik team
Share this question
or