Save Image not formatting correctly

A forum dedicated to WPF version of LightningChart Ultimate.

Moderator: Arction_LasseP

symbolick
Posts: 49
Joined: Thu May 16, 2013 8:24 pm

Save Image not formatting correctly

Post by symbolick » Wed Jul 16, 2014 1:09 am

I have setup a feature where a user can specify a resolution to export a image of the chart using your chart.SaveToFile command. It does a good job at creating a image to the specified dimensions however it clips off the bottom of the chart and the left axis label becomes covered by the left axis values. I have somewhat managed to work around the left axis side by turning on the legend when saving to a file. However there are times that it will even clip off the axis values if they are large numbers.

Here is a example: The original chart
original image.PNG
original image.PNG (54.8 KiB) Viewed 9495 times
and this is the 1080p exported image
1080pImage.png
1080pImage.png (113.36 KiB) Viewed 9495 times
I did this using the following code:
BitmapAntialiasOptions option = new BitmapAntialiasOptions();
option.ActualPixelWeight = 1;
option.ResolutionDivider = 1;
option.BlurRadius = 0;
chart.SaveToFile(@"c:\", option, 1920, 1080);

I do not understand nor can I find any documentation on what the properties of options actually do (the name might be self explanatory but I just don't comprehend) :geek:
Can you please explain how I am using these options wrong or possibly if you know of a work around to have it format the image correctly.

Thanks,
Aaron

User avatar
ArctionPasi
Posts: 1365
Joined: Tue Mar 26, 2013 10:57 pm
Location: Finland

Re: Save Image not formatting correctly

Post by ArctionPasi » Wed Jul 16, 2014 3:00 pm

Hi Aaron,

please let the right developer get back on this when he gets back on his vacation, next week.
LightningChart Support Team, PT

ArctionTero
Posts: 42
Joined: Thu Mar 28, 2013 9:20 am

Re: Save Image not formatting correctly

Post by ArctionTero » Mon Jul 21, 2014 6:24 am

Hi Aaron,

The BitmapAntialiasOptions fields have following descriptions, which should show in the code editor, if you hover over field:

ActualPixelWeight:
- Put actualPixelWeigth to higher value to make the actual pixel effect more (not much blurred). Use 1 to get high blur effect.
ResolutionDivider:
- Use resolutionDivider to divide the output bitmap size. If you want every other and column to be in the output bitmap, put 2.
BlurRadius:
- Use blur radius >= 1. With 1, blur takes current pixel and one pixel from all directions.

I tried with our WPF demo and automatic margins set to on, and it would draw y-axis title at proper position.
If set margins by hand, the title position was also ok.

So which version of the chart you are using?
How do you initialize chart.ViewXY.AxisLayout and y-axis?
LightningChart Support Team, TK

symbolick
Posts: 49
Joined: Thu May 16, 2013 8:24 pm

Re: Save Image not formatting correctly

Post by symbolick » Mon Jul 21, 2014 5:38 pm

Hello, the version of Arction currently being used is 6.0.8_net4.

This is the settings I run on a chart before I use it

Code: Select all

   chart.BeginUpdate();

            chart.ViewXY.YAxes[0].LogZeroClamp = Double.Epsilon;
            chart.ViewXY.YAxes[0].LogBase = 10;
            chart.ThrowChartExceptions = false;
            chart.Name = chartName;

            //Chart rendering settings
            chart.ChartRenderOptions.MultiCoreProcessing = MultiCoreProcessing.AllAvailableCores;
            chart.ChartRenderOptions.AntiAliasLevel = 1;
            chart.ChartRenderOptions.ViewXY.LineSeriesEnhancedAntiAliasing = EnhancedAntiAliasing.On;


            //Chart style settings
            chart.HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch;
            chart.VerticalAlignment = System.Windows.VerticalAlignment.Stretch;
            chart.Title.MouseInteraction = false;
            chart.Title.Text = chartTitle;
            chart.Title.Color = Colors.Black;
            chart.Title.Border.Style = BorderType.None;
            chart.Title.Shadow.Style = TextShadowStyle.Off;
            if (chart.ViewXY.LegendBox == null)
                chart.ViewXY.LegendBox = new Arction.WPF.LightningChartUltimate.Views.ViewXY.LegendBoxXY();

            chart.Background = System.Windows.Media.Brushes.Transparent;

            chart.Background = System.Windows.Media.Brushes.LightGray;
            chart.ChartBackground.Color = Colors.LightGray;
            chart.ChartBackground.GradientFill = GradientFill.Solid;
            chart.ViewXY.GraphBackground.Color = Colors.LightGray;
            chart.ViewXY.GraphBackground.GradientFill = GradientFill.Solid;
            chart.BorderBrush = System.Windows.Media.Brushes.Transparent;
            chart.BorderThickness = new System.Windows.Thickness(0);
            chart.ViewXY.GraphBorderColor = Colors.Black;

            //Xaxis settings
            chart.ViewXY.XAxes[0].Title.Text = xAxisTitle;
            chart.ViewXY.XAxes[0].LabelsColor = Colors.Black;
            chart.ViewXY.XAxes[0].MajorDivTickStyle.Color = Colors.Black;
            chart.ViewXY.XAxes[0].AxisColor = Colors.Black;
            chart.ViewXY.XAxes[0].AxisThickness = 1;
            chart.ViewXY.XAxes[0].MajorGrid.Color = Colors.DarkGray;
            chart.ViewXY.XAxes[0].MinorGrid.Visible = false;
            chart.ViewXY.XAxes[0].MinorDivTickStyle.Color = Colors.Black;
            chart.ViewXY.XAxes[0].MajorGrid.Pattern = LinePattern.Solid;
            chart.ViewXY.XAxes[0].Title.Color = Colors.Black;
            chart.ViewXY.XAxes[0].Title.Shadow.DropOffset = new PointIntXY(0, 0);
            chart.ViewXY.XAxes[0].Title.Shadow.DropColor = Colors.Transparent;
            chart.ViewXY.XAxes[0].Title.Shadow.ContrastColor = Colors.Transparent;
            chart.ViewXY.XAxes[0].ScaleNibs.Size.Height = 0;
            chart.ViewXY.XAxes[0].ScaleNibs.Size.Width = 0;
            chart.ViewXY.XAxes[0].ValueType = AxisValueType.Number;
            //Yaxis settings
            chart.ViewXY.YAxes[0].Title.Text = yAxisTitle;
            chart.ViewXY.YAxes[0].LabelsColor = Colors.Black;
            chart.ViewXY.YAxes[0].MajorDivTickStyle.Color = Colors.Black;
            chart.ViewXY.YAxes[0].AxisColor = Colors.Black;
            chart.ViewXY.YAxes[0].AxisThickness = 1;
            chart.ViewXY.YAxes[0].MajorGrid.Color = Colors.DarkGray;
            chart.ViewXY.YAxes[0].MinorGrid.Visible = false;
            chart.ViewXY.YAxes[0].MinorDivTickStyle.Color = Colors.Black;
            chart.ViewXY.YAxes[0].MajorGrid.Pattern = LinePattern.Solid;
            
            // chart.ViewXY.YAxes[0].Title.Font.Size = 11;
            chart.ViewXY.YAxes[0].Title.Color = Colors.Black;
            chart.ViewXY.YAxes[0].Title.Shadow.DropOffset = new PointIntXY(0, 0);
            chart.ViewXY.YAxes[0].Title.Shadow.DropColor = Colors.Transparent;
            chart.ViewXY.YAxes[0].Title.Shadow.ContrastColor = Colors.Transparent;
            chart.ViewXY.YAxes[0].ScaleNibs.Size.Width = 0;
            chart.ViewXY.YAxes[0].ScaleNibs.Size.Height = 0;
            
            //Keep titles away from numbers rendered on the axis.
            chart.ViewXY.TitlesAutoPlacement.CheckSeriesDataOverlapping = true;
            chart.ViewXY.TitlesAutoPlacement.Enabled = true;
            chart.ViewXY.TitlesAutoPlacement.SearchCrossingPoint = true;
            chart.ViewXY.TitlesAutoPlacement.UseSeriesTitleLocationsFromForm = true;
            chart.ViewXY.TitlesAutoPlacement.CalculateMaxDistance = true;
            chart.ViewXY.TitlesAutoPlacement.MaxLocationCandidates = 100;
            if (makeLogarithmic)
            {
                chart.ViewXY.YAxes[0].ScaleType = ScaleType.Logarithmic;
                chart.ViewXY.YAxes[0].LogLabelsType = LogLabelsType.Log10Exponential;
            }

            //Zoom Pan options
            chart.ViewXY.ZoomPanOptions.CtrlEnabled = false;
            chart.ViewXY.ZoomPanOptions.AltEnabled = false;
            chart.ViewXY.ZoomPanOptions.ShiftEnabled = false;
            chart.ViewXY.ZoomPanOptions.ZoomRectLine.Color = Colors.Black;
            chart.ViewXY.ZoomPanOptions.ZoomRectLine.Pattern = LinePattern.Solid;
            chart.ViewXY.ZoomPanOptions.ZoomRectLine.Width = 2;
            chart.ViewXY.ZoomPanOptions.IgnoreZerosInLogFit = true;
            System.Windows.Forms.UserControl testControl = new System.Windows.Forms.UserControl();
            int currentDPIx;
            
            using (System.Drawing.Graphics g = testControl.CreateGraphics())
            {
                currentDPIx = (int)g.DpiX;
            }
            testControl = null;
            if (currentDPIx != 0)
            {
                double fontSize = 11 * (96 / (double)currentDPIx);


                chart.ViewXY.YAxes[0].Title.Font.Size = fontSize;
                chart.ViewXY.XAxes[0].Title.Font.Size = fontSize;
                chart.ViewXY.YAxes[0].LabelsFont.Size = fontSize;
                chart.ViewXY.XAxes[0].LabelsFont.Size = fontSize;
            }
          chart.EndUpdate();
However chart.ViewXY.AxisLayout is never used inside of my application.

Regards,
Aaron

symbolick
Posts: 49
Joined: Thu May 16, 2013 8:24 pm

Re: Save Image not formatting correctly

Post by symbolick » Tue Jul 22, 2014 6:06 pm

So i can reproduce this easily, it has to do with the initial window size: this is my sample application:

Xaml File

Code: Select all

<Window x:Class="TestChartOutput.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid Name="_mainGrid">
        <Grid.RowDefinitions>
            <RowDefinition Height="auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <Button Content="Print Image" Width="120" HorizontalAlignment="Center" Name="_buttonPrintImage" Click="_buttonPrintImage_Click"/>
        
    </Grid>
</Window>

Code behind code

Code: Select all

using Arction.WPF.LightningChartUltimate;
using Arction.WPF.LightningChartUltimate.SeriesXY;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace TestChartOutput
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        LightningChartUltimate _chart;
        public MainWindow()
        {
            InitializeComponent();
            Loaded += MainWindow_Loaded;
        }

        void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            _chart = new LightningChartUltimate("My Key");

            SeriesPoint[] sps = new SeriesPoint[1024];
            PointLineSeries pls = new PointLineSeries();
            Random r = new Random();
            for (int i = 0; i < 1024; i++)
            {
                SeriesPoint sp = new SeriesPoint(i, r.Next(10000, 100000));
                sps[i] = sp;
            }
            pls.AddPoints(sps,true);
            _chart.BeginUpdate();
            _chart.ViewXY.PointLineSeries.Add(pls);
            _chart.ViewXY.FitView();
            _chart.EndUpdate();
            _mainGrid.Children.Add(_chart);
            _chart.HorizontalAlignment = HorizontalAlignment.Stretch;
            _chart.VerticalAlignment = VerticalAlignment.Stretch;
            Grid.SetRow(_chart, 1);
        }
      
        private void _buttonPrintImage_Click(object sender, RoutedEventArgs e)
        {
            string theImgFile = GetImageFile();
            if (theImgFile == "") //No file was selected
                return;
            //Testing
            BitmapAntialiasOptions option = new BitmapAntialiasOptions();
            option.ActualPixelWeight = 1;
            option.ResolutionDivider = 1;
            option.BlurRadius = 0;

            _chart.SaveToFile(theImgFile, option, 1920, 1080);
        }
        private static string GetImageFile()
        {
            string imageFile = string.Empty;
            // Displays a SaveFileDialog so the user can save the Image
            // assigned to Button2.
            Microsoft.Win32.SaveFileDialog saveFileDialog = new Microsoft.Win32.SaveFileDialog();
            saveFileDialog.Filter = "Png Image|*.png";
            saveFileDialog.Title = "Save an Image File";
            saveFileDialog.ShowDialog();
            // If the file name is not an empty string open it for saving.
            if (saveFileDialog.FileName != "")
            {
                // Saves the Image via a FileStream created by the OpenFile method.
                imageFile = saveFileDialog.FileName;
            }
            return imageFile;
        }
    }
}
If you save the image while the window is in its unmaximized state, meaning the window is 350 height, 525 width the image will save with unreadable axis that go off the screen and cover the axes title. However if you maximize the window and save (I guess this means the image is 1080p) then it will save perfectly.

Regards,
Aaron

symbolick
Posts: 49
Joined: Thu May 16, 2013 8:24 pm

Re: Save Image not formatting correctly

Post by symbolick » Fri Jul 25, 2014 12:53 am

I have found this to be a suitable workaround.

Code: Select all

BitmapAntialiasOptions option = new BitmapAntialiasOptions();
            option.ActualPixelWeight = 1;
            option.ResolutionDivider = 1;
            option.BlurRadius = 0;
            double originalWidth = _chart.MinWidth;
            double originalHeight = _chart.MinHeight;
            _chart.MinWidth = 1920;
            _chart.MinHeight = 1080;
            _chart.InvalidateVisual();
            _chart.UpdateLayout();
            _chart.SaveToFile(theImgFile, option, 1920, 1080);
            _chart.MinWidth = originalWidth;
            _chart.MinHeight = originalHeight;
            _chart.HorizontalAlignment = HorizontalAlignment.Stretch;
            _chart.VerticalAlignment = VerticalAlignment.Stretch;
            _chart.InvalidateVisual();
            _chart.UpdateLayout();