23
votes

I'm dealing with Bitmaps in my application and for some purposes I need to create a deep copy of the Bitmap. Is there an elegant way how to do it?

I tried

Bitmap deepCopy = original.Clone();

,well apparently this doesn't create a deep copy, but shallow one. My next attempt was to create a new Bitmap

Bitmap deepCopy = new Bitmap(original);

Unfortunately this constructor is Bitmap(Image), not Bitmap(Bitmap) and Bitmap(Image) will convert my nice 8bppIndexed Pixelformat into a different one.

Another attempt was to use of a MemoryStream

public static Bitmap CreateBitmapDeepCopy(Bitmap source)
{
    Bitmap result;
    using (MemoryStream stream = new MemoryStream())
    {
        source.Save(stream, ImageFormat.Bmp);
        stream.Seek(0, SeekOrigin.Begin);
        result = new Bitmap(stream);
    }
    return result;
}

Well, this doesn't work either, since the MemoryStream has to be opened during the whole lifetime of Bitmap.

So, I've summed up all my deadends and I'd really like to see a nice elegant way of creating a Bitmap deep copy. Thanks for that :)

6

6 Answers

25
votes
B.Clone(new Rectangle(0, 0, B.Width, B.Height), B.PixelFormat)
2
votes

Another way I stumbled on that achieves the same thing is to rotate or flip the image. Under the hood that seems to create a completely new copy of the bitmap. Doing two rotations or flips lets you end up with an exact copy of the original image.

result.RotateFlip(RotateFlipType.Rotate180FlipX);
result.RotateFlip(RotateFlipType.Rotate180FlipX);
2
votes

My environment:Windows 10, Visual Studio 2015, Framework 4.5.2

It works for me.

Bitmap deepCopy = new Bitmap(original);
1
votes

You could serialize the bitmap and then deserialize it. Bitmap is serializable.

0
votes

Suppose you already have a bitmap called original with something in it

Bitmap original = new Bitmap( 200, 200 );     
Bitmap copy = new Bitmap(original.Width, original.Height);
using (Graphics graphics = Graphics.FromImage(copy))
{
  Rectangle imageRectangle = new Rectangle(0, 0, copy.Width, copy.Height);
  graphics.DrawImage( original, imageRectangle, imageRectangle, GraphicsUnit.Pixel);
}

This should create a copy of the same size, and draw the original into the copy.

0
votes

You can place the following class in your code:

public static class BitmapExtensions
{
    public static Bitmap DeepClone(this Bitmap source)
    {
        IFormatter formatter = new BinaryFormatter();
        Stream stream = new MemoryStream();
        using (stream)
        {
            formatter.Serialize(stream, source);
            stream.Seek(0, SeekOrigin.Begin);
            return (Bitmap)formatter.Deserialize(stream);
        }
    }
}

This method is adjusted to work with Bitmap. If you want to have a generic method look into the link below. By naming the method DeepClone() we remove the risk of breaking already existing code (in the answer below the method is called Clone(), so it's a override method).

Original from here: https://stackoverflow.com/a/43042865/13574233

This method takes a lot of time though. If you're looking for a good performing method, this probably isn't what you're looking for.