【问题标题】:saving WPF InkCanvas to a JPG - image is getting cropped将 WPF InkCanvas 保存为 JPG - 图像被裁剪
【发布时间】:2009-08-05 16:52:12
【问题描述】:

我有一个 WPF InkCanvas 控件,用于在我的应用程序中捕获签名。控件看起来像这样 - 它是 700x300

但是,当我将其保存为 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>

在过去,这非常有效。我无法弄清楚是什么更改导致图像在保存时发生偏移。

【问题讨论】:

  • 我为此制作了一个小样本,并使用您的确切代码保存了一个 .jpg。我制作了各种图像,但一次都无法重现此问题!它必须在其他地方 - 您可以发布您的 XAML 和其他可能相关的内容吗?

标签: wpf image inkcanvas


【解决方案1】:

我这样做时遇到了同样的问题..它在这里工作..

    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;
    } 

【讨论】:

    【解决方案2】:

    啊哈!问题在于 InkCanvas 正上方的 TextBlock txtLabel。当你删除黑线消失。

    至于为什么会这样,我还不完全确定。

    【讨论】:

    • 谢谢! - 这似乎起到了作用。希望我也明白为什么。我想我现在会删除 TextBlock,等我有更多时间深入研究时再试一次。
    • 这样做是因为您使用的是 StackPanel。各种布局面板对您的控件做了一些鬼鬼祟祟的事情......在您的情况下,您很可能会看到将偏移变换应用于您的 InkCanvas。我认为您可以通过将 InkCanvas 放在边框中来解决它。有关更多信息,请参阅此链接:blogs.msdn.com/jaimer/archive/2009/07/03/…
    • 在 InkCanvas 周围添加边框确实有帮助。只需确保您的边框和画布具有相同的尺寸即可。
    【解决方案3】:

    我的班级保存图片

         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);
        }
    

    【讨论】:

      【解决方案4】:

      和 surface.Margin = 新厚度(55,40,96,5); http://img519.imageshack.us/img519/7499/mynewimage.png

      【讨论】:

        【解决方案5】:

        杰森,我解决了这个问题。 对不起我的英语。我是俄国人。 您需要在0,0,0,0 处设置属性inkCanvas.Margin 与:

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

        在您的仓位保存设定保证金后。

        示例: http://img189.imageshack.us/img189/7499/mynewimage.png

        【讨论】:

          【解决方案6】:
            var size = new Size(inkCanvas.ActualWidth, inkCanvas.ActualHeight);
              inkCanvas.Margin = new Thickness(0, 0, 0, 0);
          
              inkCanvas.Measure(size);
              inkCanvas.Arrange(new Rect(size));
              var encoder = new PngBitmapEncoder();
              var bitmapTarget = new RenderTargetBitmap((int)size.Width, (int)size.Height, 96, 96, PixelFormats.Default);
              bitmapTarget.Render(inkCanvas);
              encoder.Frames.Add(BitmapFrame.Create(bitmapTarget));
              encoder.Save(ms); 
          

          【讨论】:

          • 从上面的代码可以消除inkCanvas边框问题。试试这个。
          【解决方案7】:

          我一直在网上寻找这个问题的答案,并尝试了大多数意见,但没有任何乐趣。然后我尝试了这个,它成功了!

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-01-31
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多