在C#/.NET中将位图序列化为XML

21

我想要对一个复杂类型(类)进行XML序列化,其中包括一个类型为System.Drawing.Bitmap的属性以及其他一些属性。

    /// <summary>
    /// Gets or sets the large icon, a 32x32 pixel image representing this face.
    /// </summary>
    /// <value>The large icon.</value>
    public Bitmap LargeIcon { get; set; }

我现在发现,使用默认的XML序列化程序对位图进行序列化不起作用,因为它没有公共的无参数构造函数,这是使用默认xml序列化程序所必需的。

我知道以下内容:

我不想引用另一个项目,也不想大幅调整我的类来允许对这些位图进行xml序列化。

难道就没有简单的方法吗?

非常感谢,Marcel

4个回答

50

我会这样做:

[XmlIgnore]
public Bitmap LargeIcon { get; set; }

[Browsable(false),EditorBrowsable(EditorBrowsableState.Never)]
[XmlElement("LargeIcon")]
public byte[] LargeIconSerialized
{
    get { // serialize
        if (LargeIcon == null) return null;
        using (MemoryStream ms = new MemoryStream()) {
            LargeIcon.Save(ms, ImageFormat.Bmp);
            return ms.ToArray();
        }
    }
    set { // deserialize
        if (value == null) {
            LargeIcon = null;
        } else {
            using (MemoryStream ms = new MemoryStream(value)) {
                LargeIcon = new Bitmap(ms);
            }
        }
    }
}

5
老实说,在使用 XmlSerializer 时,这是唯一明智的选择。实现 IXmlSerializable 只会让你陷入困境。 - Marc Gravell
我在使用这段代码时遇到了一些小问题。反序列化后,字节数组是否会自动填充?如果是的话,我需要将该数组转换为位图吗?当反序列化到bmp行时,我目前会收到“InvalidOperationException”错误。感谢您的帮助! - Pudpuduk
一个有趣的事情是,我注释掉了Byte[]的“Get”部分,即使我只是反序列化,也没有出现问题。然而,位图仍然为空,并且在“Set”部分中断点实际上从未中断。我现在感到非常困惑。 - Pudpuduk
对我来说它是有效的,但它将Format32bppArgb转换为Format32bppRgb,这不是我想要的。 - MTR
对我不起作用!我正在使用jpg进行序列化!出现ExternalException:GDI+中发生了一般错误。 - 70sCommander
显示剩余12条评论

5

您也可以实现ISerializable并使用SerializationInfo手动处理位图内容。

编辑: João是正确的:处理XML序列化的正确方法是实现IXmlSerializable,而不是ISerializable

public class MyImage : IXmlSerializable
{
    public string Name  { get; set; }
    public Bitmap Image { get; set; }

    public System.Xml.Schema.XmlSchema GetSchema()
    {
        throw new NotImplementedException();
    }

    public void ReadXml(System.Xml.XmlReader reader)
    {
        throw new NotImplementedException();
    }

    public void WriteXml(System.Xml.XmlWriter writer)
    {
        writer.WriteStartElement("Name");
        writer.WriteString(this.Name);
        writer.WriteEndElement();

        using(MemoryStream ms = new MemoryStream())
        {
            this.Image.Save(ms, ImageFormat.Bmp );
            byte[] bitmapData = ms.ToArray();
            writer.WriteStartElement("Image");
            writer.WriteBase64(bitmapData, 0, bitmapData.Length);
            writer.WriteEndElement();
        }
    }
}

2

实现IXmlSerializable接口,然后自己处理所有的序列化细节。

既然您说这是一个大型类型,并且您只有位图方面的问题,考虑采取以下措施:

public class BitmapContainer : IXmlSerializable
{
    public BitmapContainer() { }

    public Bitmap Data { get; set; }

    public XmlSchema GetSchema()
    {
        throw new NotImplementedException();
    }

    public void ReadXml(XmlReader reader)
    {
        throw new NotImplementedException();
    }

    public void WriteXml(XmlWriter writer)
    {
        throw new NotImplementedException();
    }
}

public class TypeWithBitmap
{
    public BitmapContainer MyImage { get; set; }

    public string Name { get; set; }
}

不是很实用。这将涉及到一个派生类和相当多的代码。 - Marcel

2

BitMap类并没有被设计成易于XML序列化。因此,没有简单的方法来纠正设计决策。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接