【问题标题】:Creating a completely new copy of bitmap from a bitmap in C#在 C# 中从位图创建一个全新的位图副本
【发布时间】:2017-08-19 17:30:13
【问题描述】:

我需要来自另一个位图的位图的深层副本。现在,大多数解决方案都说类似this,这不是深拷贝。这意味着当我锁定原始位图时,副本也会被锁定,因为克隆是原始位图的浅拷贝。现在以下似乎对我有用,但我不确定这是否适用于所有情况。

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;
}

我需要更好、更优雅的方式来做到这一点。否则,请指出上述代码可能失败的一些情况。 TIA

【问题讨论】:

  • 至于更优雅,您可以尝试使用BinaryFormatter 序列化为MemoryStream 并将其反序列化为新的Bitmap;如果您可以接受,则取决于所需的性能。
  • 我认为这是个好主意。谢谢。我需要尝试一下。这种性能下降对我来说不是一个交易破坏者:)

标签: c# image-processing bitmap deep-copy


【解决方案1】:

我想我已经通过使用这个 sn-p 解决了这个问题。这个想法是由Lanorkin在评论中给出的,实现是在here。希望这对以后的人有所帮助。

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);
    }
}

【讨论】:

    【解决方案2】:

    你可以像这样使用它更小更优雅的方式。

    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;
        }
    

    【讨论】:

    • 这样像素格式就会改变。假设原始图像是 8 位索引的,也可以得到 24 位索引格式和一些其他属性,否则这将是一个很好的解决方案。谢谢
    • Bitmap 有丰富的构造函数集合,其中之一如下: Bitmap copy = new Bitmap(originalImage.Width, originalImage.Height, originalImage.PixelFormat);检查可用的构造函数 - 我想你也会找到其他属性的选项。
    • 是的,我也尝试过。但问题是Graphics.FromImage(...) 方法无法处理所有类型的图像(例如,具有 8bpp 索引像素格式的图像)。我已经提交了answer,这似乎消除了所有这些问题。谢谢
    • 投反对票,因为它不会克隆位图的属性。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-21
    相关资源
    最近更新 更多