WPF save Framework as Jpg via RenderTargetBitmap, DrawingVisual, DrawingContext, RenderTargetBitamp.Render(DrawingVisual), JpegBitmapEncoder Frame Add BitmapFrame Create(rendertargetbitmap)

  private void SaveFrameworkElementAsJpg(FrameworkElement fe, string jpgFilePath, int dpi = 96)
  {
      var size = new Size(fe.ActualWidth, fe.ActualHeight);
      var renderBitmap = new RenderTargetBitmap((int)(size.Width*dipFactor),
          (int)(size.Height*dipFactor),
          dpi*dipFactor,
          dpi*dipFactor,
          PixelFormats.Pbgra32);

      var drawingVisual = new DrawingVisual();
      using (DrawingContext drawingContext = drawingVisual.RenderOpen())
      {
          var visualBrush = new VisualBrush(fe);
          drawingContext.DrawRectangle(
              visualBrush,
              null,
              new Rect(new Point(0, 0), new Point(size.Width, size.Height)));
      }

      renderBitmap.Render(drawingVisual);

      var jpgEncoder = new JpegBitmapEncoder();
      jpgEncoder.QualityLevel=95;
      jpgEncoder.Frames.Add(BitmapFrame.Create(renderBitmap));
      using (var fileStream = new FileStream(jpgFilePath, FileMode.Create))
      {
          jpgEncoder.Save(fileStream);
          MessageBox.Show($"Saved in {jpgFilePath}", "Save Chart As Jpg");
      }
  }

 

 

image

 

 

 

 

 

 

 

image

 

 

 

 

install-package LiveChartsCore.SkiaSharpView -version 2.0.0-rc5.4;
install-package LiveChartsCore.SkiaSharpView.WPF  -version 2.0.0-rc5.4;

 

 

 

//xaml
<Window x:Class="WpfApp39.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:lvc="clr-namespace:LiveChartsCore.SkiaSharpView.WPF;assembly=LiveChartsCore.SkiaSharpView.WPF"
        WindowState="Maximized"
        xmlns:local="clr-namespace:WpfApp39"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <lvc:CartesianChart
             Grid.Row="1"
             Grid.Column="1"
             Series="{Binding SinLineSeries}"
             XAxes="{Binding XValueAxes}"
             YAxes="{Binding YValueAxes}"
             ZoomMode="X"
             TooltipPosition="Top"
             LegendPosition="Top"
             DrawMargin="{Binding SinFrame}"
             Background="White">
            <lvc:CartesianChart.ContextMenu>
                <ContextMenu>
                    <MenuItem Header="Save As Jpg"
             Command="{Binding SaveAsJpgCommand}"
             CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type ContextMenu}},
             Path=PlacementTarget}" />
                </ContextMenu>
            </lvc:CartesianChart.ContextMenu>
        </lvc:CartesianChart>
    </Grid>
</Window>


//cs
using LiveChartsCore;
using LiveChartsCore.Defaults;
using LiveChartsCore.SkiaSharpView;
using LiveChartsCore.SkiaSharpView.Painting;
using SkiaSharp;
using System.Collections.ObjectModel;
using System.IO;
using System.Text;
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 WpfApp39
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            var vm = new MainVM();
            this.DataContext=vm;
        }
    }

    public class MainVM
    {
        public ISeries[] SinLineSeries { get; set; }
        public Axis[] XValueAxes { get; set; }
        public Axis[] YValueAxes { get; set; }
        public DrawMarginFrame SinFrame { get; set; }

        private double dipFactor = 2;
        public MainVM()
        {
            InitSinChart();
        }

        private void InitSinChart()
        {
            var points = new ObservableCollection<ObservablePoint>();
            for (double x = 0; x<4*Math.PI; x+=0.1)
            {
                points.Add(new ObservablePoint(x, Math.Sin(x)));
            }

            SinLineSeries=new ISeries[]
            {
                new LineSeries<ObservablePoint>
                {
                    Values=points,
                    Stroke=new SolidColorPaint(SKColors.Blue)
                    {
                        StrokeThickness=3
                    },
                    Fill=null,
                    GeometrySize=0,
                    Name="Sin(x)",
                    XToolTipLabelFormatter=x=>$"X:{x.Model!.X:F2}",
                    YToolTipLabelFormatter=y=>$"Y:{y.Model!.Y:F4}"
                }
            };

            var explicitXValues = new double[]
            {
                0,
                Math.PI/2,
                Math.PI,
                3*Math.PI/2,
                2*Math.PI,
                2.5*Math.PI,
                3*Math.PI,
                3.5*Math.PI,
                4*Math.PI
            };

            var explicitPoints = new ObservableCollection<ObservablePoint>();
            foreach (var x in explicitXValues)
            {
                explicitPoints.Add(new ObservablePoint(x, Math.Sin(x)));
            }
            
            XValueAxes = new Axis[]
            {
                new Axis
                {
                    Name = "x (radians)",
                    // Force labels at exactly our explicit points
                    ForceStepToMin = true,
                    MinStep = Math.PI/2,
                    Labeler = x =>
                    {
                        // Custom label formatting for our specific points
                        if (Math.Abs(x - 0) < 0.01) return "0";
                        if (Math.Abs(x - Math.PI/2) < 0.01) return "π/2";
                        if (Math.Abs(x - Math.PI) < 0.01) return "π";
                        if (Math.Abs(x - 3*Math.PI/2) < 0.01) return "1.5π";
                        if (Math.Abs(x - 2*Math.PI) < 0.01) return "";
                        if (Math.Abs(x - 2.5*Math.PI) < 0.01) return "2.5π";
                        if (Math.Abs(x - 3*Math.PI) < 0.01) return "";
                        if (Math.Abs(x - 3.5*Math.PI) < 0.01) return "3.5π";
                        if (Math.Abs(x - 4*Math.PI) < 0.01) return "";
                        return $"{x/Math.PI:F2}π";
                    },
                    LabelsRotation = 15,
                    TextSize = 12
                }
            };

            YValueAxes=new Axis[]
            {
                new Axis
                {
                    Name="Sin(X)",
                    MinLimit=-1.2,
                    MaxLimit=1.2,
                    Labeler=value=>$"{value:F2}"
                }
            };

            SinFrame=new DrawMarginFrame
            {
                Fill=new SolidColorPaint(SKColors.Transparent),
                Stroke=new SolidColorPaint(SKColors.LightGray, 1)
            };
        }

        private ICommand saveAsJpgCommand;
        public ICommand SaveAsJpgCommand
        {
            get
            {
                if (saveAsJpgCommand==null)
                {
                    saveAsJpgCommand=new DelCommand(SaveAsJpgCommandExecuted);
                }
                return saveAsJpgCommand;
            }
        }

        private void SaveAsJpgCommandExecuted(object? obj)
        {
            var fe = obj as FrameworkElement;
if(fe==null)
       {
        return;
       }
string jpgFilePath = $"Chart_{DateTime.Now.ToString("yyyyMMddHHmmssffff")}.jpg"; SaveFrameworkElementAsJpg(fe, jpgFilePath); } private void SaveFrameworkElementAsJpg(FrameworkElement fe, string jpgFilePath, int dpi = 96) { var size = new Size(fe.ActualWidth, fe.ActualHeight); var renderBitmap = new RenderTargetBitmap((int)(size.Width*dipFactor), (int)(size.Height*dipFactor), dpi*dipFactor, dpi*dipFactor, PixelFormats.Pbgra32); var drawingVisual = new DrawingVisual(); using (DrawingContext drawingContext = drawingVisual.RenderOpen()) { var visualBrush = new VisualBrush(fe); drawingContext.DrawRectangle( visualBrush, null, new Rect(new Point(0, 0), new Point(size.Width, size.Height))); } renderBitmap.Render(drawingVisual); var jpgEncoder = new JpegBitmapEncoder(); jpgEncoder.QualityLevel=95; jpgEncoder.Frames.Add(BitmapFrame.Create(renderBitmap)); using (var fileStream = new FileStream(jpgFilePath, FileMode.Create)) { jpgEncoder.Save(fileStream); MessageBox.Show($"Saved in {jpgFilePath}", "Save Chart As Jpg"); } } } public class DelCommand : ICommand { private readonly Action<object?> execute; private readonly Predicate<object?> canExecute; public DelCommand(Action<object?> executeValue, Predicate<object?> canExecuteValue = null) { execute=executeValue; canExecute=canExecuteValue; } public event EventHandler? CanExecuteChanged { add { CommandManager.RequerySuggested+=value; } remove { CommandManager.RequerySuggested -= value; } } public bool CanExecute(object? parameter) { return canExecute==null ? true : canExecute(parameter); } public void Execute(object? parameter) { execute(parameter); } } }

 

posted @ 2025-08-15 18:57  FredGrit  阅读(7)  评论(0)    收藏  举报