5

I need a deep copy of bitmap from another bitmap. Now, most of the solutions say something like this, which is not a deep copy. Meaning that when I lock the original bitmap, then the copy gets locked too, as the clone is a shallow copy of the original bitmap. Now the following seems to work for me, but I am not sure that will work in all cases.

public static Bitmap GetCopyOf(Bitmap originalImage)
{
    Rectangle rect = new Rectangle(0, 0, originalImage.Width, originalImage.Height);
    Bitmap retrunImage = new Bitmap(originalImage.Width, originalImage.Height, originalImage.PixelFormat);
    BitmapData srcData = originalImage.LockBits(rect, ImageLockMode.ReadOnly, originalImage.PixelFormat);
    BitmapData destData = retrunImage.LockBits(rect, ImageLockMode.WriteOnly, originalImage.PixelFormat);
    int dataLength = Math.Abs(srcData.Stride) * srcData.Height;
    byte[] data = new byte[dataLength];
    Marshal.Copy(srcData.Scan0, data, 0, data.Length);
    Marshal.Copy(data, 0, destData.Scan0, data.Length);
    destData.Stride = srcData.Stride;
    if (originalImage.Palette.Entries.Length != 0)
        retrunImage.Palette = originalImage.Palette;
    originalImage.UnlockBits(srcData);
    retrunImage.UnlockBits(destData);
    return retrunImage;
}

I need better and more elegant way of doing this. Otherwise, just point me some cases where the above code may fail. TIA

Community
  • 1
  • 1
Sumsuddin Shojib
  • 3,583
  • 3
  • 26
  • 45
  • 2
    As for more elegant you can try using `BinaryFormatter` to serialize to `MemoryStream` and deserialize from it as new `Bitmap`; it depends on required performance if it is acceptable to you. – Lanorkin Mar 27 '17 at 06:25
  • I think that is a good idea. Thanks. I will need to try on that. This performance drop is not a deal breaker for me :) – Sumsuddin Shojib Mar 27 '17 at 06:39

2 Answers2

6

I think I have solved the problem by using this snippet. The idea was given by Lanorkin in the comment and the implementaion is found here. Hope this will help somebody later.

public static T Clone<T>(T source)
{
    if (!typeof(T).IsSerializable)
    {
        throw new ArgumentException("The type must be serializable.", "source");
    }

    // Don't serialize a null object, simply return the default for that object
    if (Object.ReferenceEquals(source, null))
    {
        return default(T);
    }

    IFormatter formatter = new BinaryFormatter();
    Stream stream = new MemoryStream();
    using (stream)
    {
        formatter.Serialize(stream, source);
        stream.Seek(0, SeekOrigin.Begin);
        return (T)formatter.Deserialize(stream);
    }
}
Community
  • 1
  • 1
Sumsuddin Shojib
  • 3,583
  • 3
  • 26
  • 45
-1

You can use like this it is smaller and more elegant way.

public static Bitmap GetCopyOf(Bitmap originalImage)
    {
    Bitmap copy = new Bitmap(originalImage.Width, originalImage.Height);
    using (Graphics graphics = Graphics.FromImage(copy))
    {
      Rectangle imageRectangle = new Rectangle(0, 0, copy.Width, copy.Height);
      graphics.DrawImage( originalImage, imageRectangle, imageRectangle, GraphicsUnit.Pixel);
    }
    return copy;
    }
Erdem Köşk
  • 190
  • 1
  • 10
  • This way the pixel format gets changed. Say the original image is of 8 bit indexed can get to 24 bit Indexed format and some other properties too, otherwise this would be a good solution. Thanks – Sumsuddin Shojib Mar 27 '17 at 07:43
  • Bitmap has a rich collection of constructors, one of which is the following: Bitmap copy = new Bitmap(originalImage.Width, originalImage.Height, originalImage.PixelFormat); Check the available constructors - I guess you'll find options for the other properties as well. – rincewound Mar 28 '17 at 21:31
  • 2
    Yes, I have tried that way too. but the problem was `Graphics.FromImage(...)` method can not handle all types of images (e.g. images with 8bpp indexed pixel format). I have submitted an `answer`, which seems to eliminate all those problems. Thanks – Sumsuddin Shojib Mar 30 '17 at 09:23
  • Downvote because it doesn't clone the bitmap's properties. – tmighty Sep 19 '18 at 18:30