Base64 to Image convertion problems

So I have this piece of code to decode Base64 string:

public void Base64ToImage(string base64String)
    {
        byte[] bytes = Convert.FromBase64String(base64String);
        Image image;
        using (MemoryStream ms = new MemoryStream(bytes))
        {
            image = Image.FromStream(ms);
        }
    }

But it gives me the error: " Image does not contain a definition for ‘ForStream’ [Assembly-CSharp]
I can’t find a solution for that. I’ve included ‘using System.Drawing’ but it appears that it is not being used.
I’m struggling with the decoding process so any help would be appreciated
Thanks!

I’m not sure System.Drawing is supported in Unity, and in any case whatever you get out of it won’t be usable in Unity.

Unity has RawImage and Image for use in UI, and it has Texture2D for other use, and some functions to bridge between them.

Generally if you’re hauling down some blob-o-bytes (PNG or JPG) and want to make a Texture2D out of it, this is the API you would use:

Or on older Unity,

Okay thanks, but everywhere the “decoding” process contains this Image.FromStream function. So instead of that what should I do?

Well, @Kurt-Dekker beat me to it, but he gave you links to how you convert a byte array into a texture. If that isn’t what you want to do, then you might want to explain what you need.

Okay let’s be as clear as possible. I am downloading a JSON file that contains two strings (Images converted to base64). Then I use a foreach to loop through those 2 Images-base64. Here’s is the code:

using (var webClient = new System.Net.WebClient())
        {
            var json = webClient.DownloadString("https://storage.googleapis.com/example/Levels.json");
            string[] jsondec = JsonHelper.FromJson<string>(json);
            s = jsondec; //s is a string[]
        }
        foreach (string str in s)
        {
            byte[] decodedBytes = System.Text.Encoding.UTF8.GetBytes(str);
            Texture2D tex = new Texture2D(256, 256);
            tex.LoadRawTextureData(decodedBytes);
            GameObject go = Instantiate(buttonPrefab);
            Button b = go.AddComponent<Button>();
            go.GetComponent<RawImage>().texture = tex;
            byte[] bb = tex.EncodeToPNG();
            System.IO.File.WriteAllBytes("R:/Documents/Unity Projects/testing1/" + "Image" + ".png", bb);
        }

As u can see, I’m getting images from a json file and trying to pass them in dynamically created buttons
In debug mode it seems to be crashing on tex.LoadRawTextureData and saving the Image is giving me an image of a question mark. Have a look at this and let me know and explain further because I need to solve this. Thank you very very much

The JsonHelper is a custom class for encoding and decoding
Saving the image is just for helping purpose, i will not actually add it

Didn’t you have some Base64 somewhere in the mix?

I’ve previously encoded the images into byte array and base64 strings and then put them in a JSON file that i uploaded and then download with a web client as shown above. Here is the full code for everyone:

public void EncodeImages()
    {
        string[] base64imagesarray; //The array that i will write into the JSON file later
        List<string> base64images = new List<string>();
        string[] allfiles = Directory.GetFiles("C:/xampp/htdocs/Directory/");
        foreach (string s in allfiles)
        {
            byte[] imageArray = System.IO.File.ReadAllBytes(@s);
            string base64ImageRepresentation = Convert.ToBase64String(imageArray);
            base64images.Add(base64ImageRepresentation);

        }
        base64imagesarray = base64images.ToArray();
        string json = JsonHelper.ToJson(base64imagesarray, true);
        List<Texture2D> texlist = new List<Texture2D>();
        WriteDataToFile(json);
        string[] jsonString = JsonHelper.FromJson<string>(json);
        foreach (string s in jsonString)
        {
            Base64ToImage(s, texlist, JSONdec); //JSONdec is a string[]
        }
    }


    public void Base64ToImage(string base64String, List<Texture2D> list, string[] s)
    {
        using (var webClient = new System.Net.WebClient())
        {
            var json = webClient.DownloadString("https://storage.googleapis.com/example/Levels.json");
            string[] jsondec = JsonHelper.FromJson<string>(json);
            s = jsondec;
        }
        foreach (string str in s)
        {
            byte[] decodedBytes = System.Text.Encoding.UTF8.GetBytes(str);
            Texture2D tex = new Texture2D(256, 256);
            tex.LoadRawTextureData(decodedBytes);
            GameObject go = Instantiate(buttonPrefab);
            Button b = go.AddComponent<Button>();
            go.GetComponent<RawImage>().texture = tex;
            
        }
    }

For further info, let me know

Maybe I’m blind or I don’t understand something but what I see is that you’re converting your images INTO base64, but when you recreate the images in the Base64ToImage I do not see the FromBase64String command anywhere.

byte[] decodedBytes = System.Text.Encoding.UTF8.GetBytes(str);
Texture2D tex = new Texture2D(256, 256);

I think you will need a Convert.FromBase64String somewhere here.

You damn right it isn’t there, nice catch. But where should I put it? Before decodedbytes or after?

Since you convert the bytearray when you’re encoding, I think you will need to put the System.Text.Encoding.UTF8.GetBytes(str) inside the decode. I guess, but I’m not sure, it’s already 3:30am here and I haven’t sleep yet so I wouldn’t trust my judgement. :smile:

Go get some sleep man, Thanks for the help, but come back tomorrow if you want, I really need help. Have a good night

I’ve finally managed to make it work on Unity Player with this code:

using (var webClient = new System.Net.WebClient())
        {
            var json = webClient.DownloadString("https://storage.googleapis.com/test/L.json");
            items[] jsondec = JsonHelper.FromJson<items>(json); //items is a custom class with fields of name and base64code
            s = jsondec;
        }
        foreach (items str in s)
        {
            byte[] imageBytes = Convert.FromBase64String(str.base64code);
            Texture2D tex = new Texture2D(256, 256);
            tex.LoadImage(imageBytes);
            tex.name = str.name;
            GameObject go = Instantiate(buttonPrefab);
            Button b = go.AddComponent<Button>();
            go.GetComponent<RawImage>().texture = tex;

But when I go to my cloud and put an updated L.json or delete it completely, the webclient still downloads the old file (even if it doesn’t exist on the cloud anymore). What could be wrong?
If i update the file or delete and wait for some time(maybe half an hour) it works fine and I get the content of the updated file so I guess it has to do something with cache or something

1 Like

Pretty common for a lot of CDNs to cache stuff, either geographically or temporally, usually for performance and bandwidth benefit purposes.

Depending on the hosting service it may be possible to eliminate some or all of this lag before updating.

Yeah I thought something like that. Anyway I got it working for now, thanks everyone so much for the help, highly appreciated!

You just need to disable caching in your WebClient. Stackoverflow question about exactly this issue.

Thanks but i’ve already tried that and something seems to not be working properly. It’s okay though, i’ll just have to wait some time for it to get updated automatically