WPF WriteableBitmap通过GDI+绘制帮助类
代码:
public class WriteableBitmapGraphic : IDisposable
{
public WriteableBitmap Source { get; private set; }
public System.Drawing.Bitmap bitmap { get; private set; }
public int DataLength { get; private set; }
public Int32Rect SourceRect { get; private set; }
public System.Drawing.Rectangle BitmapRect { get; private set; }
public System.Drawing.Graphics Graphics { get; private set; }
System.Drawing.Imaging.PixelFormat pixelFormat;
bool flushed = false;
public WriteableBitmapGraphic(WriteableBitmap writeableBitmap)
{
Source = writeableBitmap;
DataLength = Source.BackBufferStride * Source.PixelHeight;
SourceRect = new Int32Rect(0, 0, Source.PixelWidth, Source.PixelHeight);
BitmapRect = DrawingUtil.ConvertRect(SourceRect);
pixelFormat = System.Drawing.Imaging.PixelFormat.Format32bppArgb;
bitmap = new System.Drawing.Bitmap(writeableBitmap.PixelWidth, writeableBitmap.PixelHeight, pixelFormat);
Graphics = System.Drawing.Graphics.FromImage(bitmap);
}
public void FillSource()
{
var block = bitmap.LockBits(BitmapRect, System.Drawing.Imaging.ImageLockMode.WriteOnly, pixelFormat);
byte[] tempArr = new byte[DataLength];
Marshal.Copy(Source.BackBuffer, tempArr, 0, DataLength);
Marshal.Copy(tempArr, 0, block.Scan0, DataLength);
bitmap.UnlockBits(block);
}
public void DrawImage(byte[] pixelArray, int width, int height, int x, int y)
{
using (System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(width, height, pixelFormat))
{
var block = bitmap.LockBits(new System.Drawing.Rectangle(0, 0, width, height), System.Drawing.Imaging.ImageLockMode.WriteOnly, bitmap.PixelFormat);
Marshal.Copy(pixelArray, 0, block.Scan0, pixelArray.Length);
bitmap.UnlockBits(block);
DrawImage(bitmap, x, y);
}
}
public void DrawImage(string imagePath, Point point)
{
using (var image = System.Drawing.Image.FromFile(imagePath))
DrawImage(image, point);
}
public void DrawImage(System.Drawing.Image image, Point point)
{
DrawImage(image, (int)point.X, (int)point.Y);
}
public void DrawImage(System.Drawing.Image image, int x, int y)
{
Graphics.DrawImage(image, x, y);
}
public void ClearRandom()
{
Random random = new Random();
var block = bitmap.LockBits(BitmapRect, System.Drawing.Imaging.ImageLockMode.ReadOnly, pixelFormat);
int offset = 0;
int n256 = 256;
unsafe
{
byte* ptr = (byte*)block.Scan0;
do
{
ptr[offset++] = (byte)random.Next(n256);
} while (offset < DataLength);
}
bitmap.UnlockBits(block);
}
public void Flush()
{
Graphics.Flush();
var block = bitmap.LockBits(BitmapRect, System.Drawing.Imaging.ImageLockMode.ReadOnly, pixelFormat);
byte[] tempArr = new byte[DataLength];
Marshal.Copy(block.Scan0, tempArr, 0, DataLength);
Source.Lock();
Source.AddDirtyRect(SourceRect);
Marshal.Copy(tempArr, 0, Source.BackBuffer, DataLength);
Source.Unlock();
bitmap.UnlockBits(block);
flushed = true;
}
public void Dispose()
{
if(!flushed)
Flush();
Graphics?.Dispose();
bitmap?.Dispose();
}
public void Clear(Color color)
{
Graphics.Clear(DrawingUtil.ConvertColor(color));
}
}
public static class DrawingUtil
{
public static System.Drawing.SolidBrush CreateBrush(System.Windows.Media.Color color)
{
return new System.Drawing.SolidBrush(ConvertColor(color));
}
public static System.Drawing.Color ConvertColor(System.Windows.Media.Color color)
{
return System.Drawing.Color.FromArgb(color.A, color.R, color.G, color.B);
}
public static System.Drawing.Rectangle ConvertRect(System.Windows.Int32Rect rect)
{
return new System.Drawing.Rectangle(rect.X, rect.Y, rect.Width, rect.Height);
}
}
public class CvGraphic : IDisposable
{
public WriteableBitmap Source { get; private set; }
public OpenCvSharp.Mat SourceMat { get; private set; }
public int Length { get; private set; }
bool flushed = false;
public CvGraphic(WriteableBitmap source)
{
Source = source;
Length = source.PixelHeight * source.BackBufferStride;
SourceMat = OpenCvSharp.Mat.FromPixelData(source.PixelHeight, source.PixelWidth, OpenCvSharp.MatType.CV_8UC4, source.BackBuffer);
}
public void Clear()
{
OpenCvSharp.Cv2.Randn(SourceMat, new OpenCvSharp.Vec4b(0, 0, 0, 0), new OpenCvSharp.Vec4b(0, 0, 0, 0));
}
public void Random()
{
OpenCvSharp.Cv2.Randn(SourceMat, new OpenCvSharp.Vec4b(0, 0, 0, 0), new OpenCvSharp.Vec4b(255, 255, 255, 255));
}
public void DrawImage(string filename, int x, int y)
{
if (x >= Source.PixelWidth || y >= Source.PixelHeight) return;
using(OpenCvSharp.Mat mat = new OpenCvSharp.Mat(filename, OpenCvSharp.ImreadModes.Unchanged))
{
int width = Math.Min(SourceMat.Width - x, mat.Width);
int height = Math.Min(SourceMat.Height - y, mat.Height);
mat.CopyTo(SourceMat.SubMat(new OpenCvSharp.Range(x, x + width), new OpenCvSharp.Range(y, y + height)));
}
}
public void Flush()
{
Source.WritePixels(new Int32Rect(0, 0, Source.PixelWidth, Source.PixelHeight), SourceMat.Data, Length, Source.BackBufferStride);
flushed = true;
}
public void Dispose()
{
if(flushed)
Flush();
SourceMat?.Dispose();
}
}