将 wpf 图像控件保存到文件的最简单方法

Posted

技术标签:

【中文标题】将 wpf 图像控件保存到文件的最简单方法【英文标题】:Easiest way of saving wpf Image control to a file 【发布时间】:2012-05-15 07:08:17 【问题描述】:

我的 wpf 应用程序中有一个 Image 控件,里面有一个大图像,但控件本身只有 60x150,这意味着它只显示该图像的某个部分。 将可见部分保存到文件的最简单方法是什么?

感谢您的帮助。

[编辑] 我最终使用了找到 here 的代码(在此处发布之前我无法找到)...

Grid r = new Grid();
        r.Background = new ImageBrush(image2.Source);


    System.Windows.Size sz = new System.Windows.Size(image2.Source.Width, image2.Source.Height);
    r.Measure(sz);
    r.Arrange(new Rect(sz));

    RenderTargetBitmap rtb = new RenderTargetBitmap((int)image2.Source.Width, (int)image2.Source.Height, 96d, 96d, PixelFormats.Default);
    rtb.Render(r);

    BmpBitmapEncoder encoder = new BmpBitmapEncoder();
    encoder.Frames.Add(BitmapFrame.Create(rtb));

    FileStream fs = File.Open(@"C:\lol.png", FileMode.Create);
    encoder.Save(fs);
    fs.Close();

【问题讨论】:

【参考方案1】:

您可以使用RenderTargetBitmap 类和BitmapEncoder。

定义这些方法:

void SaveToBmp(FrameworkElement visual, string fileName)

    var encoder = new BmpBitmapEncoder();
    SaveUsingEncoder(visual, fileName, encoder);


void SaveToPng(FrameworkElement visual, string fileName)

    var encoder = new PngBitmapEncoder();
    SaveUsingEncoder(visual, fileName, encoder);


// and so on for other encoders (if you want)


void SaveUsingEncoder(FrameworkElement visual, string fileName, BitmapEncoder encoder)

    RenderTargetBitmap bitmap = new RenderTargetBitmap((int)visual.ActualWidth, (int)visual.ActualHeight, 96, 96, PixelFormats.Pbgra32);
    bitmap.Render(visual);
    BitmapFrame frame = BitmapFrame.Create(bitmap);
    encoder.Frames.Add(frame);

    using (var stream = File.Create(fileName))
    
        encoder.Save(stream);
    

如果您在这样的容器中拥有 Image 控件:

<Grid x:Name="MyGrid">
    <Image Name="MyImage" Stretch="None"></Image>
</Grid>

你只需要这样做:

SaveToPng(MyGrid, "image.png");

否则,您可以在使用 RenderTargetBitmap 时简单地传递所需的尺寸:

SaveToPng(MyImage, "image.png");

...

RenderTargetBitmap bitmap = new RenderTargetBitmap(YourWidth, YourHeight, 96, 96, PixelFormats.Pbgra32);

【讨论】:

谢谢你,如果不是因为一个小问题,那就太棒了。保存的图像是漆黑的......有什么想法是如何发生的或如何解决它? 我已经在 VB.NET 中完成了一个测试项目:here it is a sample 如果它可以提供帮助;和here XAML。 @gilderkite 我假设你说“MyImage”是指 WPF 中的图像控件,那么是的,我已经尝试过了 @Capt.Morgan 是的,我的意思是你的Image 控制权。试试我的例子,它有效。 @Capt.Morgan,我知道这很旧,但我遇到了同样的问题,您需要将渲染控件放在没有边距的父控件上,如下所述:weblog.west-wind.com/posts/2007/Sep/10/…【参考方案2】:

在使用 gliderkite 的解决方案时,我遇到了与其他人相同的“黑色”图像问题。 “黑色”图像似乎是由于 FrameworkElement 的边距导致它在捕获的图像之外呈现。我在comment on Rick Stahl's blog 中找到了解决方法

具体来说,在渲染之前进行测量和排列使它有机会调整自己以适应图片中没有边距的事实。以下是我现在重新用于屏幕截图的静态类。这是基于 gliderkite 的回答和 Rick Stahl 博客上的信息。

public static class ScreenCapture

    public static void SaveToBmp(FrameworkElement visual, string fileName)
    
        var encoder = new BmpBitmapEncoder();
        SaveUsingEncoder(visual, fileName, encoder);
    

    public static void SaveToPng(FrameworkElement visual, string fileName)
    
        var encoder = new PngBitmapEncoder();
        SaveUsingEncoder(visual, fileName, encoder);
    

    public static void SaveToJpeg(FrameworkElement visual, string fileName)
    
        var encoder = new JpegBitmapEncoder();
        SaveUsingEncoder(visual, fileName, encoder);
    

    private static void SaveUsingEncoder(FrameworkElement visual, string fileName, BitmapEncoder encoder)
    
        RenderTargetBitmap bitmap = new RenderTargetBitmap((int)visual.ActualWidth, (int)visual.ActualHeight, 96, 96, PixelFormats.Pbgra32);
        Size visualSize = new Size(visual.ActualWidth, visual.ActualHeight);
        visual.Measure(visualSize);
        visual.Arrange(new Rect(visualSize));
        bitmap.Render(visual);
        BitmapFrame frame = BitmapFrame.Create(bitmap);
        encoder.Frames.Add(frame);

        using (var stream = File.Create(fileName))
        
            encoder.Save(stream);
        
    

【讨论】:

我尝试了其他方法,但是渲染图像的宽度和高度总是太小,这意味着我在图像的底部和右侧有内容被截断。但是,使用这种方法,我得到了我期望的确切尺寸。不知道为什么...

以上是关于将 wpf 图像控件保存到文件的最简单方法的主要内容,如果未能解决你的问题,请参考以下文章

c# winform 如何给report.rdlc 图像控件,添加我电脑里保存的图片?

在 VB.net 中保存设置的最简单方法是啥

WPF/XAML:使用相同事件的多个控件 - 有没有更简单的方法?

在文件中存储对象/充满对象的地图的最简单方法是啥?

将图像设置为 JPanel 背景的最简单方法

访问 Azure 文件存储的最简单方法是啥?