How can I save an image from ink canvas?

2.5k views Asked by At

I am trying to save an image from ink canvas however it does not create any file after saving, this is my code:

RenderTargetBitmap rtb = new RenderTargetBitmap(
    (int)canvas.Width, (int)canvas.Height, 0, 0, PixelFormats.Default);

rtb.Render(this.canvas);

JpegBitmapEncoder encoder = new JpegBitmapEncoder();

encoder.Frames.Add(BitmapFrame.Create(rtb));

using(var file = new FileStream(@"C:\test.jpg", FileMode.Create))
{
   encoder.Save(file);
}

however it does not create any file even when I change the directory. No exceptions is invoked and no errors are shown. The code just ran normally without any problem but the file meant to be generated is not there.

3

There are 3 answers

0
Prabhdeep Singh On

Ok here is one way I did it, this way exports a "test.png" in debug folder. The way is simple, firstly create a InkCanvas I will name it ink for the purposes of this example. Also create a button that has a on click event handler. In that buttons on click event handler paste this.

InkCanvasWindow.xaml.cs

Rect bounds = VisualTreeHelper.GetDescendantBounds(ink);
            double dpi = 96d;

            RenderTargetBitmap rtb = new RenderTargetBitmap((int)bounds.Width, (int)bounds.Height, dpi, dpi, System.Windows.Media.PixelFormats.Default);
            DrawingVisual dv = new DrawingVisual();
            using (DrawingContext dc = dv.RenderOpen())
            {
                VisualBrush vb = new VisualBrush(ink);
                dc.DrawRectangle(vb, null, new Rect(new Point(), bounds.Size));
            }
            rtb.Render(dv);

            BitmapEncoder pngEncoder = new PngBi tmapEncoder();
            pngEncoder.Frames.Add(BitmapFrame.Create(rtb));
            using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
            {
                pngEncoder.Save(ms);
                System.IO.File.WriteAllBytes("test.png", ms.ToArray());
  • REMEBER "ink" is the InkCanvas name.
2
Sandeep Jadhav On

XAML

    <Window x:Class="WpfInkCavasSaveImage.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow"  Height="1091" Width="873" WindowState="Maximized">
        <Grid Margin="0,0,0,173" >
            <Grid.RowDefinitions>
                <RowDefinition Height="1200*" />
                <RowDefinition Height="50" />
            </Grid.RowDefinitions>    
            <InkCanvas HorizontalAlignment="Stretch" Margin="1,1,1,10" x:Name="inkCanvas1" VerticalAlignment="Stretch" Width="Auto" RenderTransformOrigin="0.5,0.5" Background="LightGreen" SnapsToDevicePixels="True" IsManipulationEnabled ="True"  Grid.RowSpan="2">
                <InkCanvas.CacheMode>
                    <BitmapCache/>
                </InkCanvas.CacheMode>
                <InkCanvas.DefaultDrawingAttributes>
                    <DrawingAttributes Color="Black" FitToCurve="True" Height="2.0031496062992127" IgnorePressure="False" IsHighlighter="False" StylusTip="Ellipse" StylusTipTransform="Identity" Width="2.0031496062992127"/>    
                </InkCanvas.DefaultDrawingAttributes>
            </InkCanvas>
            <Button x:Name="btnSaveImage" Content="Save Ink Canvas" Height="41" Width="155" Canvas.Left="100" Canvas.Top="900"  VerticalAlignment="Top" HorizontalAlignment="Left" RenderTransformOrigin="1.417,14.6" Margin="15,93,0,-84" Background="SkyBlue" Click="btnSaveInkCanvas" Grid.Row="1" BorderBrush="{x:Null}"/>
        </Grid>
        
    </Window>

C#

    using Microsoft.Win32;
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Security.AccessControl;
    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 WpfInkCavasSaveImage
    {
        /// <summary>
        /// Interaction logic for MainWindow.xaml
        /// </summary>
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
                inkCanvas1.Width = System.Windows.SystemParameters.WorkArea.Width;
                inkCanvas1.Height = System.Windows.SystemParameters.WorkArea.Height;
            }
            private void btnSaveInkCanvas(object sender, RoutedEventArgs e)
            {
                string subpath = Directory.GetCurrentDirectory();
                SaveFileDialog saveFileDialog12 = new SaveFileDialog();
                saveFileDialog12.Filter = "JPeg Image|*.jpg|Bitmap Image|*.bmp|Gif Image|*.gif|Png File|*.png";
                saveFileDialog12.Title = "Save an Image File";
                saveFileDialog12.InitialDirectory = subpath;
                saveFileDialog12.ShowDialog();
    
                if (saveFileDialog12.FileName == "") return;
                subpath = saveFileDialog12.FileName.Substring(0, saveFileDialog12.FileName.Length - saveFileDialog12.SafeFileName.Length);
           
                RenderTargetBitmap rtb = new RenderTargetBitmap((int)inkCanvas1.Width, (int)inkCanvas1.Height, 96d, 96d, PixelFormats.Default);
                rtb.Render(inkCanvas1);
                DrawingVisual dvInk = new DrawingVisual();
                DrawingContext dcInk = dvInk.RenderOpen();
                dcInk.DrawRectangle(inkCanvas1.Background, null, new Rect(0d, 0d, inkCanvas1.Width, inkCanvas1.Height));
                foreach (System.Windows.Ink.Stroke stroke in inkCanvas1.Strokes)
                {
                    stroke.Draw(dcInk);
                }
                dcInk.Close();
    
                FileStream fs = File.Open(saveFileDialog12.FileName, FileMode.OpenOrCreate);//save bitmap to file
                System.Windows.Media.Imaging.JpegBitmapEncoder encoder1 = new JpegBitmapEncoder();
                encoder1.Frames.Add(BitmapFrame.Create(rtb));
                encoder1.Save(fs);
                fs.Close();
            }
        }
    }
0
Kym NT On

try using a Save File Dialog

Here is an example code i used in my class "add signature" in vb.net

upon button click a savefile dialog box will appear, after putting a file name and pressing save, it will be save as a png image(i used pngBitmap Encoder)

This has same format with what you are using but with a save file dialog added.

btw. WPFControl.Inkcanvas1 is my inkcanvas

'buttonSaveAsClick


   'open save file dialog box
    Dim sfd As New SaveFileDialog()
    sfd.Filter = "Png Files(*.png)|*.png"

    'save file as png (render bitmap and convert/save to png)
    Dim result As Nullable(Of Boolean) = sfd.ShowDialog()
    Dim fileName As String = ""

    If result = True Then
        fileName = sfd.FileName

        Dim size As Size = New Point(750, 400) '= WPFControl.InkCanvas1.RenderSize 
        Console.WriteLine(WPFControl.InkCanvas1.RenderSize)
        Dim rtb As New RenderTargetBitmap(CInt(size.Width), CInt(size.Height), 96, 96, Windows.Media.PixelFormats.Pbgra32)
        rtb.Render(WPFControl.InkCanvas1)
        Dim png As New PngBitmapEncoder()
        png.Frames.Add(BitmapFrame.Create(rtb))
        If String.IsNullOrEmpty(fileName) = True Then
            MsgBox("Please Enter a File Name", MsgBoxStyle.Exclamation, "File Name required!")
            Exit Sub

        Else
            Console.WriteLine(sfd.FileName)
            Console.WriteLine(convertImage.ConvertImageFiletoBytes(sfd.FileName))
        End If


        Using stm As Stream = File.Create(fileName)
            png.Save(stm)

        End Using
    End If