C# 复制位图数据(GDI+;)

C# 复制位图数据(GDI+;),c#,bitmap,gdi+,C#,Bitmap,Gdi+,我目前正在用C#开发一个游戏引擎,使用GDI+。目前,我正试图通过实现一种更快的方式将一个位图复制到另一个位图,从而使图形引擎渲染位图的速度更快 我有一个方法叫做CopyBitmap,它接收你想要复制的位图、你想要复制到的位图、目标矩形(你想要复制图像的位置和大小)和源矩形(你想要复制图像的部分) 但是,我不知道如何设置复制图像的位置和大小 我该怎么做呢 以下是我目前掌握的代码: /// <summary> /// Copies the <see cref="B

我目前正在用C#开发一个游戏引擎,使用GDI+。目前,我正试图通过实现一种更快的方式将一个位图复制到另一个位图,从而使图形引擎渲染位图的速度更快

我有一个方法叫做
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);
        }
    }