将画布保存为位图
本文关键字:位图 保存 布保存 | 更新日期: 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 中
尝试将画布背景颜色设置为白色