C# 共享源位图的绘制

C# 共享源位图的绘制,c#,bitmap,drawing,share,pixel,C#,Bitmap,Drawing,Share,Pixel,我通过从另一个中提取200x200正方形来创建一个新位图。我认为源(位图像素)由这两个共享。现在,当我在原始图像上画一个圆圈时,副本上也有一个圆圈。但当我用另一种方式做这件事时——在新创建的圆上画一个圆——在原来的圆上没有圆。为什么会发生这种情况?我以为源像素是共享的 private Bitmap testa(Bitmap bmp) { System.Drawing.Imaging.BitmapData bmpData = bmp.LockBits(new Rec

我通过从另一个中提取200x200正方形来创建一个新位图。我认为源(位图像素)由这两个共享。现在,当我在原始图像上画一个圆圈时,副本上也有一个圆圈。但当我用另一种方式做这件事时——在新创建的圆上画一个圆——在原来的圆上没有圆。为什么会发生这种情况?我以为源像素是共享的

    private Bitmap testa(Bitmap bmp)
    {
        System.Drawing.Imaging.BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, bmp.PixelFormat);

        //Create a new bitmap.
        Bitmap newBitmap = new Bitmap(200, 200, bmpData.Stride, bmp.PixelFormat, bmpData.Scan0);

        bmp.UnlockBits(bmpData);

        // Draw the new bitmap.
        using (Graphics g = Graphics.FromImage(bmp)) // or: newBitmap
        {
            g.DrawEllipse(new Pen(Brushes.Red), 1, 1, 100, 100);
        }
        return newBitmap;
    }

基本上,您错误地使用了
LockBits()
Bitmap()
构造函数,因此无论您看到什么行为,都是纯粹的学术性和不确定的

传递给
位图(int,int,int,PixelFormat,IntPtr)的
IntPtr
构造函数必须是为该特定位图分配的构造函数。你必须确保这一点

另一方面,
BitmapData.Scan0
指针保证仅在调用
UnlockBits()
之前保持有效。在这一点上,它可能会也可能不会

如果您感到好奇,尝试其他实验可能会很有趣,比如在原始位图上绘制,查看新位图,然后在新位图上绘制,查看原始位图,最后再次在原始位图上绘制并查看新位图


但无论你在这样的实验中发现什么样的行为,你都不能依赖它,因为这种行为没有记录,也不受支持。据我所知,没有支持的机制允许两个不同的
Bitmap
对象共享同一个缓冲区。它似乎在某些孤立的情况下起作用纯粹是运气。

我不认为你真的“共享”了像素。您只能复制它们(带或不带圆圈)。还有:为什么不使用DrawImage复制?它的格式就是这样@TaW那么为什么我先复制图像,然后再在上面绘制时,两幅图像上都会显示圆圈?对于DrawImage:这只是一个示例,我只有IntPtr可从整个位图中复制。我们看到了相关代码吗?我没有阅读链接页面的备注部分,但我的示例也来自于此。这就解释了这么多。谢谢从IntPtr复制位图有什么建议?我应该像这样创建tmp位图,然后克隆它吗?我个人?除非你把速度看得比方便重要得多,否则我一点也不会搞砸
LockBits()
。要精确复制位图,只需使用
位图(图像)
构造函数。如果要裁剪位图,请创建一个新的
bitmap
对象,按所需大小调用
Graphics.FromImage(Image)
传递新位图,然后使用
Graphics.DrawImage()
方法将原始位图中需要的部分绘制到新位图中。如果需要速度,可以使用
LockBits()
,但即使在那里,我也会让GDI+为您分配缓冲区。创建所需大小的空新位图,对原始位图和新位图调用
LockBits()
,然后将字节从一个缓冲区复制到另一个缓冲区(例如,使用
Marshal.copy()
)。