Serialising and De-serialising Images

August 28, 2022

For another project that I’m working on, I needed to transfer an image as text. In fact, that’s actually quite an easy thing to do in .Net. The way is to use a BinaryWriter and BinaryReader.

Binary Serialisation Helpers

The first step is to create a helper to serialise or de-serialise anything to or from binary. We’ll start with Serialise:



string SerialiseToBinary<TData>(TData data)
{
    string serialised = JsonSerializer.Serialize(data);

    using var stream = new MemoryStream();
    using var binary = new BinaryWriter(stream);
    binary.Write(serialised);

    stream.Flush();
    stream.Position = 0;
    return Convert.ToBase64String(stream.ToArray());
}

We start by simply calling the JSON serialise method - that way, anything that’s passed in is now a string. Then we need a stream to write to - in fact, you could do this directly to a file, but here we’re just using a memory stream. Finally we convert to Base64 (Conversion to Base 64 isn’t strictly necessary for this, but if you want to send the binary data anywhere afterwards then it may be).

Next is the Deserialise method:



TData? DeserialiseFromBinary<TData>(string data)
{
    byte[] b = Convert.FromBase64String(data);
    using var stream = new MemoryStream(b);
    using var br = new BinaryReader(stream);

    stream.Seek(0, SeekOrigin.Begin);
    var resultString = br.ReadString();
    var result = JsonSerializer.Deserialize<TData>(resultString);
    return result;
}


Here we’re converting from Base 64 - which obviously is necessary if you’ve encoded with it on the other side. Then we have the same in reverse - using the binary reader to read the memory stream, and then de-serialise the result.

Writing and Reading from Files

Now that we can write and read binary data, we can add a couple of other helpers to do this from a file - for this experiment, I’m simply copying an image:



string SerialiseImageToBinary(string path)
{
    var bytes = File.ReadAllBytes(path);
    var serialised = SerialiseToBinary(bytes);
    return serialised;
}

void DeserialiseImageFromBinary(string data, string outPath)
{    
    var deserialised = DeserialiseFromBinary<byte[]>(data);
    using var fs = new FileStream(outPath, FileMode.CreateNew);
    fs.Write(deserialised);    
}

Probably not worth going into too much detail on these methods: they simply read and write from files, calling our other helper methods. I then call them like this:



        var serialised = SerialiseImageToBinary(
            @"c:\\tmp\\testimg.png");
        Console.WriteLine(serialised);

        DeserialiseImageFromBinary(
            serialised,
            @"c:\\tmp\\testimg2.png");

I’ll be coming back to these methods in future posts around transmitting this information over Azure Service Bus.



Profile picture

A blog about one man's journey through code… and some pictures of the Peak District
Twitter

© Paul Michaels 2024