C# 复制位图数据(GDI+;)
我目前正在用C#开发一个游戏引擎,使用GDI+。目前,我正试图通过实现一种更快的方式将一个位图复制到另一个位图,从而使图形引擎渲染位图的速度更快 我有一个方法叫做C# 复制位图数据(GDI+;),c#,bitmap,gdi+,C#,Bitmap,Gdi+,我目前正在用C#开发一个游戏引擎,使用GDI+。目前,我正试图通过实现一种更快的方式将一个位图复制到另一个位图,从而使图形引擎渲染位图的速度更快 我有一个方法叫做CopyBitmap,它接收你想要复制的位图、你想要复制到的位图、目标矩形(你想要复制图像的位置和大小)和源矩形(你想要复制图像的部分) 但是,我不知道如何设置复制图像的位置和大小 我该怎么做呢 以下是我目前掌握的代码: /// <summary> /// Copies the <see cref="B
CopyBitmap
,它接收你想要复制的位图、你想要复制到的位图、目标矩形(你想要复制图像的位置和大小)和源矩形(你想要复制图像的部分)
但是,我不知道如何设置复制图像的位置和大小
我该怎么做呢
以下是我目前掌握的代码:
/// <summary>
/// Copies the <see cref="BitmapData"/> from one <see cref="Bitmap"/> to another.
/// </summary>
/// <param name="from">The <see cref="Bitmap"/> you wish to copy from.</param>
/// <param name="to">The <see cref="Bitmap"/> you wish to copy to.</param>
/// <param name="destRect">The location and size of the copied image.</param>
/// <param name="srcRect">The portion of the image you wish to copy.</param>
public static void CopyBitmap(Bitmap from, Bitmap to, Rectangle destRect, Rectangle srcRect)
{
// The bitmap we're copying from needs to know the portion of the bitmap we wish to copy
// so lets pass it the src rect, it is also read only.
BitmapData fromData = from.LockBits(srcRect, ImageLockMode.ReadOnly, PixelFormat.Format32bppPArgb);
// The bitmap we're copying to needs to know where the copied bitmap should be placed, and also how big it is
// so lets pass it the dest rect, it is also write only
BitmapData toData = to.LockBits(destRect, ImageLockMode.WriteOnly, PixelFormat.Format32bppPArgb);
// Declare an array to hold the bytes of data we're copying from
int bytes = Math.Abs(fromData.Stride) * from.Height;
// convert it to bytes
byte[] rgbValues = new byte[bytes];
// I imaginge here is where I should set the position and size of the image I wish to copy to it's destRect
// Copy the values to the bitmap we're copying to
System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, toData.Scan0, bytes);
// unlock them both
from.UnlockBits(fromData);
to.UnlockBits(toData);
}
//
///从一个复制到另一个。
///
///您希望从中复制的文件。
///您要复制到的文件。
///复制图像的位置和大小。
///要复制的图像部分。
公共静态void CopyBitmap(位图从、位图到、矩形析取、矩形srrect)
{
//我们从中复制的位图需要知道要复制的位图部分
//让我们把它传递给src rect,它也是只读的。
BitmapData fromData=from.LockBits(srrect、ImageLockMode.ReadOnly、PixelFormat.Format32bppPArgb);
//我们要复制到的位图需要知道复制的位图应该放在哪里,以及它有多大
//所以让我们把它传递给dest rect,它也是只写的
BitmapData toData=to.LockBits(析取、ImageLockMode.WriteOnly、PixelFormat.Format32bppPArgb);
//声明一个数组以保存我们从中复制的数据字节
int字节=Math.Abs(fromData.Stride)*from.Height;
//将其转换为字节
字节[]rgbValues=新字节[字节];
//我想这里是我应该设置的位置和大小的图像,我希望复制到它的析取
//将值复制到要复制到的位图
System.Runtime.InteropServices.Marshal.Copy(rgbvalue,0,toData.Scan0,字节);
//两个都解锁
from.解锁位(fromData);
至.解锁位(toData);
}
我认为值得一提的是,我不希望使用graphics.DrawImage
方法,因为这就是我首先创建该方法的原因。位图包含“GetPixel”和“SetPixel”函数。我认为您可以使用它将位图数据复制到ToBitmap数据
GetPixel返回颜色,SetPixel相同
请试一试。我已经做了一些假设,向您展示了一个如何做到这一点的示例,并且我还使用了
不安全的
代码来为您提供尽可能高的性能
作出的假设:
PixelFormat
s为Format32bppPArgb
每像素4字节srcRect
和dstRect
具有相同的宽度和高度公共静态无效复制位图(位图从、位图到、矩形析取、矩形srrect)
{
//检查矩形是否适当对齐
//你应该得到这个和图像的像素格式正确
//除非你也可以采用相同的格式
const int BYTES_/u像素=4;
BitmapData fromData=from.LockBits(新矩形(Point.Empty,from.Size)、ImageLockMode.ReadOnly、PixelFormat.Format32bppPArgb);
尝试
{
BitmapData toData=to.LockBits(新矩形(Point.Empty,to.Size)、ImageLockMode.WriteOnly、PixelFormat.Format32bppPArgb);
尝试
{
//在本例中,我将假设srcRect和destRect具有相同的宽度和高度
int xOffset=(destect.X-srrect.X)*每像素字节数;
int yOffset=destect.Y-srrect.Y;
对于(int hi=srrect.Y,hc=srrect.Bottom;hi
BitmapData类不包含SetPixel或GetPixel方法,只有Bitmap类包含。这些方法也非常慢,因此OP想要使用LockBits
侧注,您需要检查destect
和srrect
是否正确地位于相应图像的范围内谢谢,我现在就做。显然,id是用一个简单的矩形来实现的。IntersectsWith check?你可以按你的意愿来做,但这应该是可行的。让我们来看看。@MathewO'Dwyer刚刚用一个包含alpha分量的图像尝试了我的代码,结果正确,所以我无法重现你丢失alpha通道的结果
public static unsafe void CopyBitmap(Bitmap from, Bitmap to, Rectangle destRect, Rectangle srcRect)
{
//Check rects line up appropriatley
//You should get this and the PixelFormat's of the images properly
//unless you can alsways assume the same format
const int BYTES_PER_PIXEL = 4;
BitmapData fromData = from.LockBits(new Rectangle(Point.Empty, from.Size), ImageLockMode.ReadOnly, PixelFormat.Format32bppPArgb);
try
{
BitmapData toData = to.LockBits(new Rectangle(Point.Empty, to.Size), ImageLockMode.WriteOnly, PixelFormat.Format32bppPArgb);
try
{
//For the purpose of this example I will assume that srcRect and destRect have the same width and height
int xOffset = (destRect.X - srcRect.X) * BYTES_PER_PIXEL;
int yOffset = destRect.Y - srcRect.Y;
for (int hi = srcRect.Y, hc = srcRect.Bottom; hi < hc; ++hi)
{
byte* fromRow = (byte*)fromData.Scan0 + (hi * fromData.Stride);
byte* toRow = (byte*)toData.Scan0 + ((hi + yOffset) * toData.Stride);
for (int wi = (srcRect.X * BYTES_PER_PIXEL), wc = (srcRect.Right * BYTES_PER_PIXEL);
wi < wc; wi += BYTES_PER_PIXEL)
{
//Adjust this if you have a different format
toRow[xOffset + wi] = fromRow[wi];
toRow[xOffset + wi + 1] = fromRow[wi + 1];
toRow[xOffset + wi + 2] = fromRow[wi + 2];
toRow[xOffset + wi + 3] = fromRow[wi + 3];
}
}
}
finally
{
to.UnlockBits(fromData);
}
}
finally
{
from.UnlockBits(fromData);
}
}