将画布保存为位图

本文关键字:位图 保存 布保存 | 更新日期: 2023-09-27 17:53:59

我想将画布保存为位图。我在网上找到了一些例子,但所有这些都只保存了黑色图像(和我的画布一样大(。我能用这个做什么?

代码:

    public static void SaveCanvasToFile(Canvas surface, string filename)
    {
        Size size = new Size(surface.Width, surface.Height);
        surface.Measure(size);
        surface.Arrange(new Rect(size));
        // Create a render bitmap and push the surface to it
        RenderTargetBitmap renderBitmap =
          new RenderTargetBitmap(
            (int)size.Width,
            (int)size.Height,
            96d,
            96d,
            PixelFormats.Pbgra32);
        renderBitmap.Render(surface);
        // Create a file stream for saving image
        using (FileStream outStream = new FileStream(filename, FileMode.Create))
        {               
            BmpBitmapEncoder encoder = new BmpBitmapEncoder();
            // push the rendered bitmap to it
            encoder.Frames.Add(BitmapFrame.Create(renderBitmap));
            // save the data to the stream
            encoder.Save(outStream);
        }}

将画布保存为位图

试试这个答案:

public void ExportToPng(Uri path, Canvas surface)
{
  if (path == null) return;
  // Save current canvas transform
  Transform transform = surface.LayoutTransform;
  // reset current transform (in case it is scaled or rotated)
  surface.LayoutTransform = null;
  // Get the size of canvas
  Size size = new Size(surface.Width, surface.Height);
  // Measure and arrange the surface
  // VERY IMPORTANT
  surface.Measure(size);
  surface.Arrange(new Rect(size));
  // Create a render bitmap and push the surface to it
  RenderTargetBitmap renderBitmap = 
    new RenderTargetBitmap(
      (int)size.Width, 
      (int)size.Height, 
      96d, 
      96d, 
      PixelFormats.Pbgra32);
  renderBitmap.Render(surface);
  // Create a file stream for saving image
  using (FileStream outStream = new FileStream(path.LocalPath, FileMode.Create))
  {
    // Use png encoder for our data
    PngBitmapEncoder encoder = new PngBitmapEncoder();
    // push the rendered bitmap to it
    encoder.Frames.Add(BitmapFrame.Create(renderBitmap));
    // save the data to the stream
    encoder.Save(outStream);
  }
  // Restore previously saved layout
  surface.LayoutTransform = transform;
}

为了方便起见,这个答案是从[本页]复制到这里的====链路失效(http://denisvuyka.wordpress.com/2007/12/03/wpf-diagramming-saving-you-canvas-to-image-xps-document-or-raw-xaml/)

在我的渲染代码中,我在target.Arrange(new Rect(size));之后调用target.UpdateLayout();,也许这会解决问题。还要注意,如果画布背景没有设置,它将被渲染为透明,而编码为BMP,它可能会变成纯黑,所以如果你只有黑色对象,它们可能是不可见的。

var fileName = "img.jpg";
var bitMap = new WriteableBitmap(DrawCanvas, null);
var ms = new MemoryStream();
System.Windows.Media.Imaging.Extensions.SaveJpeg(bitMap, ms, bitMap.PixelWidth, bitMap.PixelHeight, 0, 100);
ms.Seek(0, SeekOrigin.Begin);
var library = new MediaLibrary();
library.SavePicture(string.Format("{0}", fileName), ms);

注意

如果渲染为黑色图像,则是因为大小不正确。

这是一个很好的例子:

RenderTargetBitmap rtb = new RenderTargetBitmap(width, height, mXdpi, mYdpi, System.Windows.Media.PixelFormats.Default);
        rtb.Render(my_canvas);
        BitmapEncoder pngEncoder = new PngBitmapEncoder();
        pngEncoder.Frames.Add(BitmapFrame.Create(rtb));
        using (var fs = System.IO.File.OpenWrite("test.png"))
        {
            pngEncoder.Save(fs);
        }

这段代码从画布上渲染的位图中保存一个png图像。

希望能帮助你。

如果您使用的是windows 10 UWP应用程序,请查看此页面:

Microsoft Docs 上的RenderTargetBitmap类

作为奖励,UWP简化了流程。

using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Effects;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
public static class RenderVisualService
{
    public const double defaultDpi = 96.0;
    public static void SaveAsPng(this FrameworkElement frElement, string fullFilePath, FormattedText title = null, Point pt = default(Point))
    {
        BitmapImage img = RenderVisualService.RenderToPNGImageSource(frElement, title, pt) as BitmapImage;
        img.SavePng(fullFilePath);
    }
    public static ImageSource RenderToPNGImageSource(Visual targetControl, FormattedText Title = null, Point pt = default(Point))
    {
        var renderTargetBitmap = targetControl.GetRenderTargetBitmapFromControl(Title);
        var encoder = new System.Windows.Media.Imaging.PngBitmapEncoder();
        encoder.Frames.Add(System.Windows.Media.Imaging.BitmapFrame.Create(renderTargetBitmap));
        var result = new System.Windows.Media.Imaging.BitmapImage();
        using (var memoryStream = new System.IO.MemoryStream())
        {
            encoder.Save(memoryStream);
            memoryStream.Seek(0, System.IO.SeekOrigin.Begin);
            result.BeginInit();
            result.CacheOption = System.Windows.Media.Imaging.BitmapCacheOption.OnLoad;
            result.StreamSource = memoryStream;
            result.EndInit();
        }
        return result;
    }
    public static RenderTargetBitmap ExportToPng(this Shape shape, Uri path)
    {
        // Save current canvas transform
        Transform transform = shape.LayoutTransform;
        // reset current transform (in case it is scaled or rotated)
        shape.LayoutTransform = null;
        // Get the size of canvas
        Size size;
        //if (!sizeOfShape.HasValue) size = new Size(shape.Width, shape.Height);
        //else size = sizeOfShape.Value;
        // Measure and arrange the surface
        // VERY IMPORTANT
        shape.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
        size = shape.DesiredSize;
        shape.Arrange(new Rect(size));
        // Create a render bitmap and push the surface to it
        RenderTargetBitmap renderBitmap = new RenderTargetBitmap((int)size.Width, (int)size.Height, 96d, 96d, PixelFormats.Pbgra32);
        renderBitmap.Render(shape);
        if (path == null) return renderBitmap;
        // Create a file stream for saving image
        using (FileStream outStream = new FileStream(path.LocalPath, FileMode.Create))
        {
            // Use png encoder for our data
            PngBitmapEncoder encoder = new PngBitmapEncoder();
            // push the rendered bitmap to it
            encoder.Frames.Add(BitmapFrame.Create(renderBitmap));
            // save the data to the stream
            encoder.Save(outStream);
        }
        // Restore previously saved layout
        shape.LayoutTransform = transform;
        return renderBitmap;
    }
    public static RenderTargetBitmap ExportToPng(this Canvas surface, String path, Size? sizeOfCanvas = null)
    {
        // Save current canvas transform
        Transform transform = surface.LayoutTransform;
        // reset current transform (in case it is scaled or rotated)
        var OldTransform = surface.LayoutTransform;
        surface.LayoutTransform = null;
        try
        {
            // Get the size of canvas
            Size size;
            if (!sizeOfCanvas.HasValue) size = new Size(surface.Width, surface.Height);
            else size = sizeOfCanvas.Value;
            //Size sizeR = new Size(300, 300);
            // Measure and arrange the surface
            // VERY IMPORTANT
            surface.Measure(size);
            surface.Arrange(new Rect(size));
            // Create a render bitmap and push the surface to it
            RenderTargetBitmap renderBitmap = new RenderTargetBitmap((int)size.Width, (int)size.Height, 96d, 96d, PixelFormats.Pbgra32);
            renderBitmap.Render(surface);
            if (path == null) return renderBitmap;
            // Create a file stream for saving image
            using (FileStream outStream = new FileStream(path, FileMode.Create))
            {
                // Use png encoder for our data
                PngBitmapEncoder encoder = new PngBitmapEncoder();
                // push the rendered bitmap to it
                encoder.Frames.Add(BitmapFrame.Create(renderBitmap));
                // save the data to the stream
                encoder.Save(outStream);
            }
            // Restore previously saved layout
            surface.LayoutTransform = transform;
            return renderBitmap;
        }
        catch { return null; }
        finally { surface.LayoutTransform = OldTransform; }
    }
    public static void SaveBitmapSourceToPNGFile(System.Windows.Media.Imaging.BitmapSource renderTargetBitmap, string filename)
    {
        var encoder = new System.Windows.Media.Imaging.PngBitmapEncoder();
        encoder.Frames.Add(System.Windows.Media.Imaging.BitmapFrame.Create(renderTargetBitmap));
        var result = new System.Windows.Media.Imaging.BitmapImage();
        try { using (var fileStream = new System.IO.FileStream(filename, System.IO.FileMode.Create)) { encoder.Save(fileStream); } }
        catch (Exception ex) { System.Diagnostics.Debug.WriteLine($"There was an error saving the file: {ex.ProcessException()}"); }
    }
    public static System.Windows.Media.Imaging.BitmapSource GetRenderTargetBitmapFromControl(this Visual targetControl, FormattedText Title, Point ptTitlePosition = default(Point), double dpi = defaultDpi)
    {
        if (targetControl == null) return null;
        var bounds = VisualTreeHelper.GetDescendantBounds(targetControl);
        //int pixelX = (int)bounds.Width; int pixelY = (int)bounds.Height;
        //IntPtr hDc = Helper.GetDC(IntPtr.Zero);
        //if (hDc != IntPtr.Zero)
        //{
        //    int dpiX = Helper.GetDeviceCaps(hDc, Helper.LOGPIXELSX);
        //    int dpiY = Helper.GetDeviceCaps(hDc, Helper.LOGPIXELSY);
        //    Helper.ReleaseDC(IntPtr.Zero, hDc);
        //    pixelX = (int)(((double)dpiX / 96) * (double)bounds.Width);
        //    pixelY = (int)(((double)dpiY / 96) * (double)bounds.Height);
        //}
        var renderTargetBitmap = new System.Windows.Media.Imaging.RenderTargetBitmap(/*(int)(bounds.Width * dpi / 96.0),(int)(bounds.Height * dpi / 96.0),*/(int)bounds.Size.Width, (int)bounds.Size.Height, dpi, dpi, PixelFormats.Pbgra32);
        var drawingVisual = new DrawingVisual();
        using (DrawingContext dc = drawingVisual.RenderOpen())
        {
            var visualBrush = new VisualBrush(targetControl);
            dc.DrawRectangle(visualBrush, null, new Rect(new Point(), bounds.Size));
            if (null != Title) dc.DrawText(Title, ptTitlePosition);
        }
        renderTargetBitmap.Render(drawingVisual);
        //Clipboard.SetImage(renderTargetBitmap);
        return renderTargetBitmap;
    }
    public static Size GetDimensionsFromWindowToPixel(this ScrollViewer scroller)
    {
        IntPtr hDc = Helper.GetDC(IntPtr.Zero);
        double pixelX = -10, pixelY = -10;
        if (hDc != IntPtr.Zero)
        {
            int dpiX = Helper.GetDeviceCaps(hDc, Helper.LOGPIXELSX);
            int dpiY = Helper.GetDeviceCaps(hDc, Helper.LOGPIXELSY);
            Helper.ReleaseDC(IntPtr.Zero, hDc);
            pixelX = (int)(((double)dpiX / 96) * (double)(scroller.ActualWidth - SystemParameters.VerticalScrollBarWidth));
            pixelY = (int)(((double)dpiY / 96) * (double)(scroller.ActualHeight - SystemParameters.HorizontalScrollBarHeight));
        }
        Size sz = new Size(0, 0);
        if (pixelX > 0) sz.Width = pixelX; if (pixelY > 0) sz.Height = pixelY;
        return sz;
    }
    /// <summary>
    /// This method is almost same as RenderVisualService.SaveAsPng , this method explores the range of possibilites in one place
    /// which is also an extension Method , this one has some cool arguments</summary>
    /// <param name="fr"></param>
    /// <param name="pngIsTrueAndClipBoardisFalse"></param> <param name="pngFileFullPath"></param>
    /// <param name="x"></param> <param name="y"></param>
    /// <param name="wd"></param> <param name="ht"></param>
    /// <param name="margin"></param>
    /// <param name="dotsPerInch"></param>
    public static void DumpFrameworkElementToPng(this FrameworkElement fr, bool pngIsTrueAndClipBoardisFalse = true, String pngFileFullPath = @"C:'WOI'A'control.png", int x = 0, int y = 0, int wd = 0, int ht = 0, int margin = 20, int border = 5, double dotsPerInch = 96.0)
    {
        Directory.CreateDirectory(System.IO.Path.GetDirectoryName(pngFileFullPath));
        System.Windows.Media.PixelFormat pf = System.Windows.Media.PixelFormats.Pbgra32;
        GeneralTransform t = fr.TransformToVisual(fr.Parent as Visual);
        Vector topLeft = (Vector)t.Transform(new Point(0, 0));
        Vector topRight = (Vector)t.Transform(new Point(fr.ActualWidth, 0));
        Vector botmLeft = (Vector)t.Transform(new Point(0, fr.ActualHeight));
        double renderedWidth = (topRight - topLeft).Length; double widthScale = renderedWidth / fr.ActualWidth;
        double renderedHight = (botmLeft - topLeft).Length; double heightScale = renderedHight / fr.ActualHeight;
        //int fullWidth = (int)fr.ActualWidth + 2 * margin; int fullHeight = (int)fr.ActualHeight + 2 * margin;
        int fullWidth = (int)renderedWidth + (2 * margin); int fullHeight = (int)renderedHight + (2 * margin);
        var renderTargetBitmap = new RenderTargetBitmap(fullWidth, fullHeight, dotsPerInch, dotsPerInch, pf);
        var drawingVisual = new System.Windows.Media.DrawingVisual();
        RenderOptions.SetBitmapScalingMode(drawingVisual, BitmapScalingMode.HighQuality);
        using (System.Windows.Media.DrawingContext dc = drawingVisual.RenderOpen())
        {
            var vb = new System.Windows.Media.VisualBrush(fr);
            dc.DrawRectangle(Brushes.AliceBlue, null, new Rect(0, 0, fullWidth, fullHeight));
            dc.DrawRectangle(vb, null, new Rect(margin, margin, fullWidth, fullHeight));
        }
        renderTargetBitmap.Render(drawingVisual);
        BitmapSource bmpSource = renderTargetBitmap;
        if (wd != 0 && ht != 0)
        {
            if (wd > fr.ActualWidth || ht > fr.ActualHeight)
            {
                wd = fullWidth; ht = fullHeight;
                x = y = 0;
            }
            else { wd -= margin; ht -= margin; }
            bmpSource = new CroppedBitmap(renderTargetBitmap, new Int32Rect(x + margin, y + margin, wd, ht));
            if (margin != 0)
            {
                var dv = new DrawingVisual();
                using (var dc = dv.RenderOpen())
                {
                    fullWidth = wd + 2 * margin; fullHeight = ht + 2 * margin;
                    dc.DrawRectangle(Brushes.AliceBlue, null, new Rect(0, 0, fullWidth, fullHeight));
                    dc.DrawImage(bmpSource, new Rect(margin, margin, wd, ht));
                    if (border != 0) dc.DrawRectangle(null, new Pen(Brushes.DarkBlue, border), new Rect(margin - border / 2, margin - border / 2, wd + border, ht + border));
                }
                renderTargetBitmap = new RenderTargetBitmap(fullWidth, fullHeight, dotsPerInch, dotsPerInch, pf);
                renderTargetBitmap.Render(dv);
                bmpSource = new CroppedBitmap(renderTargetBitmap, new Int32Rect(0, 0, fullWidth, fullHeight));
            }
        }
        if (pngIsTrueAndClipBoardisFalse)
        {
            bmpSource.SavePng(pngFileFullPath);
            Helper.ShellExecute(IntPtr.Zero, "open", pngFileFullPath, null, null, 1);
        }
        else
        {
            Clipboard.SetImage(bmpSource);
            Helper.ShellExecute(IntPtr.Zero, "open", "pBrush", null, null, 1);
        }
    }
    /// <summary>
    /// Applicable to methods like MakeJulia_Sai in SpecialCanvas
    /// Usage : RenderVisualService.SaveARenderMethodToPng(Kanva.MakeJulia_Sai, Kanva.ActualWidth / 4, Kanva.ActualHeight / 4);
    /// </summary>
    /// <param name="method"></param>
    public static void SaveARenderMethodToPngOrClipBoard(Action<System.Windows.Media.DrawingContext> method, double wd, double ht, bool pngIsTrueAndClipBoardisFalse = true, String pngFileFullPath = @"C:'WOI'A'Bindu.png")
    {
        double dotsPerInch = 96.0; System.Windows.Media.PixelFormat pf = System.Windows.Media.PixelFormats.Pbgra32;
        //double wd = Kanva.ActualWidth / 4; double ht = Kanva.ActualHeight / 4;
        var renderTargetBitmap = new System.Windows.Media.Imaging.RenderTargetBitmap((int)wd, (int)ht, dotsPerInch, RenderVisualService.defaultDpi, pf);
        var drawingVisual = new System.Windows.Media.DrawingVisual();
        using (System.Windows.Media.DrawingContext dc = drawingVisual.RenderOpen()) method(dc);
        renderTargetBitmap.Render(drawingVisual);
        if (pngIsTrueAndClipBoardisFalse)
        {
            Directory.CreateDirectory(System.IO.Path.GetDirectoryName(pngFileFullPath));
            renderTargetBitmap.SavePng(pngFileFullPath);
            Helper.ShellExecute(IntPtr.Zero, "open", pngFileFullPath, null, null, 1);
        }
        else Clipboard.SetImage(renderTargetBitmap);
    }
}

我最喜欢

Kanva.DumpFrameworkElementToPng(pngIsTrueAndClipBoardisFalse: false)

其中Kanva是一些画布,里面有一些控件、图像等。调用DumpFrameworkElementToPng(…(后,图像保存在ClipBoard 中

尝试将画布背景颜色设置为白色