сохранение WPF InkCanvas в JPG - изображение обрезается

У меня есть элемент управления WPF InkCanvas, который я использую для захвата подписи в своем приложении. Контроллер выглядит вот так - это 700х300

альтернативный текст

Однако, когда я сохраняю его в формате JPG, результирующее изображение выглядит так же, 700x300

альтернативный текст

Код, который я использую для сохранения

            sigPath = System.IO.Path.GetTempFileName();

            MemoryStream ms = new MemoryStream();
            FileStream fs = new FileStream(sigPath, FileMode.Create);

            RenderTargetBitmap rtb = new RenderTargetBitmap((int)inkSig.Width, (int)inkSig.Height, 96d, 96d, PixelFormats.Default);
            rtb.Render(inkSig);
            JpegBitmapEncoder encoder = new JpegBitmapEncoder();
            encoder.Frames.Add(BitmapFrame.Create(rtb));

            encoder.Save(fs);
            fs.Close();

Это XAML, который я использую:

<Window x:Class="Consent.Client.SigPanel"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Background="Transparent" Topmost="True" AllowsTransparency="True"
Title="SigPanel" Left="0" Top="0" Height="1024" Width="768" WindowStyle ="None" ShowInTaskbar="False" ResizeMode="NoResize" WindowStartupLocation="CenterScreen" >

<Border BorderThickness="1" BorderBrush="Black" Background='#FFFFFFFF' x:Name='DocumentRoot' Width='750' Height='400' CornerRadius='10'>
    <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
        <TextBlock Name="txtLabel" FontSize="24" HorizontalAlignment="Center" >Label</TextBlock>
        <InkCanvas Opacity="1" Background="Beige" Name="inkSig" Width="700" Height="300" />

        <StackPanel HorizontalAlignment="Center" Orientation="Horizontal">
            <Button FontSize="24" Margin="10" Width="150" Name="btnSave" Click="btnSave_Click">Save</Button>
            <Button FontSize="24" Margin="10" Width="150" Name="btnCancel" Click="btnCancel_Click">Cancel</Button>
            <Button FontSize="24" Margin="10" Width="150" Name="btnClear" Click="btnClear_Click">Clear</Button>
        </StackPanel>
    </StackPanel>
</Border>

In the past this worked perfectly. I can't figure out what changed that is causing the image to shift when it is saved.


person Jason    schedule 05.08.2009    source источник
comment
Я сделал небольшой образец для этого и использовал ваш точный код, чтобы сохранить .jpg. Сделал множество образов и ни разу не смог воспроизвести эту проблему! Это должно быть где-то еще — можете ли вы опубликовать свой XAML и что-нибудь еще, что может иметь значение?   -  person Charlie    schedule 05.08.2009


Ответы (7)


Ага! Проблема заключается в том, что TextBlock txtLabel находится прямо над InkCanvas. Когда вы удалите это, черная полоса исчезнет.

Что касается того, почему это происходит, я еще не совсем уверен.

person Charlie    schedule 05.08.2009
comment
Благодарность! - казалось, это помогло. Хотел бы я тоже понять, почему. Думаю, сейчас я удалю TextBlock и попробую позже, когда у меня будет больше времени, чтобы вникнуть в это. - person Jason; 06.08.2009
comment
Это происходит потому, что вы используете StackPanel. Различные панели макета делают некоторые скрытые вещи с вашими элементами управления... в вашем случае вы, скорее всего, видите преобразование смещения, применяемое к вашему InkCanvas. Я думаю, вы можете обойти это, поместив свой InkCanvas в границу. См. эту ссылку для получения дополнительной информации: blogs.msdn.com /jaimer/archive/2009/07/03/ - person Adam Sills; 09.10.2009
comment
Добавление границы вокруг InkCanvas действительно помогает. Просто убедитесь, что границы и холст имеют одинаковые размеры. - person David De Sloovere; 04.03.2014

У меня была такая же проблема, как и у меня. Здесь это сработало.

    private void Button_Click(object sender, RoutedEventArgs e)
    {           
        double width = inkSig.ActualWidth;
        double height = inkSig.ActualHeight;
        RenderTargetBitmap bmpCopied = new RenderTargetBitmap((int)Math.Round(width), (int)Math.Round(height), 96, 96, PixelFormats.Default);
        DrawingVisual dv = new DrawingVisual();
        using (DrawingContext dc = dv.RenderOpen())
        {
            VisualBrush vb = new VisualBrush(inkSig);
            dc.DrawRectangle(vb, null, new Rect(new System.Windows.Point(), new System.Windows.Size(width, height)));
        }
        bmpCopied.Render(dv);
        System.Drawing.Bitmap bitmap;
        using (MemoryStream outStream = new MemoryStream())
        {
            // from System.Media.BitmapImage to System.Drawing.Bitmap 
            BitmapEncoder enc = new BmpBitmapEncoder();
            enc.Frames.Add(BitmapFrame.Create(bmpCopied));
            enc.Save(outStream);
            bitmap = new System.Drawing.Bitmap(outStream);
        }

        EncoderParameter qualityParam =
     new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 85L);

        // Jpeg image codec
        ImageCodecInfo jpegCodec = getEncoderInfo("image/jpeg");

        if (jpegCodec == null)
            return;

        EncoderParameters encoderParams = new EncoderParameters(1);
        encoderParams.Param[0] = qualityParam;
        Bitmap btm = new Bitmap(bitmap);
        bitmap.Dispose();
        btm.Save("C:\\Users\\Pd\\Desktop\\dfe12.jpg", jpegCodec, encoderParams);
        btm.Dispose(); 
    }

    private ImageCodecInfo getEncoderInfo(string mimeType)
    {
        // Get image codecs for all image formats
        ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();

        // Find the correct image codec
        for (int i = 0; i < codecs.Length; i++)
            if (codecs[i].MimeType == mimeType)
                return codecs[i];
        return null;
    } 
person Erman    schedule 02.01.2011

Мой класс сохранить изображение

     using System;
     using System.IO;
     using System.Windows;
     using System.Windows.Controls;
     using System.Windows.Media;
     using System.Windows.Media.Imaging;

     public void ExportToJpeg(String path,  InkCanvas surface)
    {
        double
                x1 = surface.Margin.Left,
                x2 = surface.Margin.Top,
                x3 = surface.Margin.Right,
                x4 = surface.Margin.Bottom;

        if (path == null) return;

        surface.Margin = new Thickness(0, 0, 0, 0);

      Size size = new Size(surface.Width, surface.Height);
   surface.Measure(size);
   surface.Arrange(new Rect(size));

         RenderTargetBitmap renderBitmap =
          new RenderTargetBitmap(
            (int)size.Width,
            (int)size.Height,
            96,
            96,
            PixelFormats.Default);
      renderBitmap.Render(surface);
      using (FileStream fs = File.Open(path, FileMode.Create))
        {
         JpegBitmapEncoder encoder = new JpegBitmapEncoder();
            encoder.Frames.Add(BitmapFrame.Create(renderBitmap));
            encoder.Save(fs);
        }
      surface.Margin = new Thickness(x1, x2, x3, x4);
    }
person Community    schedule 31.12.2009

и surface.Margin = новая толщина (55,40,96,5); http://img519.imageshack.us/img519/7499/mynewimage.png

person Community    schedule 31.12.2009

Джейсон, я решил эту проблему. Извините мой английский. Я русский. Вам нужно установить свойство inkCanvas.Margin в 0,0,0,0 с помощью:

surface.Margin = new Thickness(0, 0, 0, 0);

после сохранения установленной маржи по вашей позиции.

пример: http://img189.imageshack.us/img189/7499/mynewimage.png< /а>

person Community    schedule 31.12.2009

Я искал по всей сети ответ на эту проблему и пробовал большинство мнений без какой-либо радости. Тогда я попробовал это, и это сработало!

<Canvas x:Name="editCanvas" Background="Transparent" ClipToBounds="True">
        <InkCanvas EditingMode="Select" x:Name="inkCanvas"  Background="Transparent" Height="562" Width="866">

        </InkCanvas>
</Canvas>
person user4964503    schedule 02.06.2015

person    schedule
comment
Из приведенного выше кода проблема с границей inkCanvas может быть устранена. Попробуй это. - person ; 14.10.2014