Easiest way of saving wpf Image control to a file

 ̄綄美尐妖づ 提交于 2019-12-17 10:49:34

问题


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 this image. What is the easiest way of saving the visible portion to a file?

Thank you for your help.

[EDIT] I ended up using code found here (which I've not been able to locate before posting 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:


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



回答2:


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


来源:https://stackoverflow.com/questions/10470841/easiest-way-of-saving-wpf-image-control-to-a-file

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!