Easiest way of saving wpf Image control to a file

前端 未结 2 1160
清歌不尽
清歌不尽 2020-12-03 01:59

I have a Image control inside my wpf application, which has a large image inside of it, but the control itself is only 60x150, this means it only shows a certain portion of

相关标签:
2条回答
  • 2020-12-03 02:40

    You could use RenderTargetBitmap class and BitmapEncoder.

    Define these methods:

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

    If you have your Image control inside a container like this:

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

    You just need to do so:

    SaveToPng(MyGrid, "image.png");
    

    Otherwise you can simply pass the dimensions you want when you use RenderTargetBitmap:

    SaveToPng(MyImage, "image.png");
    
    ...
    
    RenderTargetBitmap bitmap = new RenderTargetBitmap(YourWidth, YourHeight, 96, 96, PixelFormats.Pbgra32);
    
    0 讨论(0)
  • 2020-12-03 02:49

    I ran into the same 'black' image issue that other did when using gliderkite's solution. The 'black' image appears to be due to the FrameworkElement's margin causing it to get rendered outside of the captured image. I found the workaround in a comment on Rick Stahl's blog

    Specifically, measuring and arranging prior to rendering gives it a chance to adjust itself to the fact there are no margins in the picture. The following is a static class I now re-use for screen captures. This is based of of gliderkite's answer and the information on Rick Stahl's blog.

    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);
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题