Search code examples
c#xmlxnamonogametexture2d

XNA / Monogame Texture2D to to string


I want to store a small png image in a XML file and Load it back to Texture2D.

This is what I'm doing

Code for saving

I'm writing the data of the Texture2D with the BinaryWriter to a MemoryStream,

then converting the MemoryStream to an Array. I have to Convert the array to a Base64String because you can't save all characters

in a XML file.

The string is saved in my XML file.

    public static string SaveTextureData(this Texture2D texture)
    {
        int width = texture.Width;
        int height = texture.Height;
        Color[] data = new Color[width * height];
        texture.GetData<Color>(data, 0, data.Length);

        MemoryStream streamOut = new MemoryStream();

        BinaryWriter writer = new BinaryWriter(streamOut);

           writer.Write(width);
            writer.Write(height);
            writer.Write(data.Length);

            for (int i = 0; i < data.Length; i++)
            {
                writer.Write(data[i].R);
                writer.Write(data[i].G);
                writer.Write(data[i].B);
                writer.Write(data[i].A);
            } 

        return Convert.ToBase64String(streamOut.ToArray());
    }

Code for Loading

Same here.. I'm converting the Base64Str to an array and trying to read it.

But I cant read it back.

    public static Texture2D LoadTextureData(this string gfxdata, GraphicsDevice gfxdev)
    {
        byte[] arr = Convert.FromBase64String(gfxdata);

        MemoryStream input = new MemoryStream();

        BinaryWriter bw = new BinaryWriter(input);
        bw.Write(arr);

        using (BinaryReader reader = new BinaryReader(input))
        {
            var width = reader.ReadInt32();
            var height = reader.ReadInt32();
            var length = reader.ReadInt32();
            var data = new Color[length];

            for (int i = 0; i < data.Length; i++)
            {
                var r = reader.ReadByte();
                var g = reader.ReadByte();
                var b = reader.ReadByte();
                var a = reader.ReadByte();
                data[i] = new Color(r, g, b, a);
            }

            var texture = new Texture2D(gfxdev, width, height);
            texture.SetData<Color>(data, 0, data.Length);
            return texture;
        }
    }

Could need some help here.

Getting an exception in the reading method that the value couldnt read. in line

var width = reader.ReadInt32();


Solution

  • Just create a MemoryStream directly from your byte array, no need to fill it with a writer:

            byte[] arr = Convert.FromBase64String(gfxdata);
    
            using (var ms = new MemoryStream(arr))
            using (var reader = new BinaryReader(ms))
            {
                var width = reader.ReadInt32();
                var height = reader.ReadInt32();
                var length = reader.ReadInt32();
                var data = new Color[length];
    
                for (int i = 0; i < data.Length; i++)
                {
                    var r = reader.ReadByte();
                    var g = reader.ReadByte();
                    var b = reader.ReadByte();
                    var a = reader.ReadByte();
                    data[i] = new Color(r, g, b, a);
                }
    
                // Allocate the Texture2D as before.
            }
    

    (The specific problem with your code is that you did not rewind your input stream after writing to it.)