0

I want to convert image(Texture2D) data to Base64 string and store in JSON format. as of now I am getting image texture, it's a kind of screenshot from live rendering camera. And I want the same image data into JSON format. Please suggest me with any example.

This is how I am converting texture to Base64 then JSON.

Application.ExternalCall("screenshot", System.Convert.ToBase64String(texture.EncodeToPNG()));
string TextureArray = System.Convert.ToBase64String(texture.EncodeToPNG());
string serializedAbilites = JsonUtility.ToJson(TextureArray);
File.WriteAllText(Application.dataPath + "/File.json", TextureArray);
  • Unity Version: 2020.3.11f1,
  • language: C#
James Z
  • 12,209
  • 10
  • 24
  • 44
  • why you need to parser to json ? does you have other data with PNG , and you need include it? – TimChang Sep 30 '21 at 01:50
  • You should not store a whole png as json, not that it is impossible but kinda wrong. You'd better store it as a byte array and then store the path in the json. – fafase Sep 30 '21 at 07:06
  • If this is for a webrequest why don't you send binary data via [`UnityWebRequest.Post`](https://docs.unity3d.com/ScriptReference/Networking.UnityWebRequest.Post.html) using a [`MultipartFormFileSection`](https://docs.unity3d.com/ScriptReference/Networking.MultipartFormFileSection.html) ? Could you tell us what exactly you are actually trying to achieve? – derHugo Sep 30 '21 at 09:05
  • @derHugo My objectives are I have created Multiple image capture where I can capture image from live rendering camera and save it to my local assets folder it's working well and am getting Texture2D but now I need to convert image data to Base64 string and store in JSON file. Every time when I capture/delete image, it should update JSON file, and next time when you start the app, it should read the JSON file first and if any image data is found, should show it in the scroll view which I have created. – Ali Hussain Oct 01 '21 at 08:00
  • @AliHussain still why JSON? Why not simply store the last file as actual PNG image file? – derHugo Oct 01 '21 at 09:25
  • @derHugo Purpose of this is I need to send data to server. So I cannot send textures directly in web request, so I need to convert it into basestring and the whole data needs to be converted as JSON. – Ali Hussain Oct 01 '21 at 21:40
  • As said before: Sure you can send binary data in a `WebRequestPost` .. link can be found in my previous comments – derHugo Oct 02 '21 at 07:36
  • @derHugo Problems were with conversion data to binary then to jSON, can you please show demonstration how to achieve this in an example actually I'm not experienced enough in it in C# and Unity. – Ali Hussain Oct 04 '21 at 07:47

2 Answers2

1

I know this kind of answer is kind of annoying but doing this is a bad idea, if you really need to save texture data you should save it as binary and not as a string, you will user more bytes, over complicate your code and in general it's not a good practice.

HOWEVER, I will still answer the question, but please avoid this. If you want to save this string as a json, you will have to specify that its serializable as c# sees strings as not suitable for serialization (this is false however: Is String not serializable by default in .Net Core?), add this behind your string and your code should work (in case you are wondering this is called an attribute, it's sort of like a tag):

[Serializable]

NOW, for the correct way of doing this we will take an example code from the unity docs (an extremely helpful tool by the way): Texture2D.EncodeToPNG

// Encode texture into PNG
        byte[] bytes = tex.EncodeToPNG();
        Object.Destroy(tex);

        // For testing purposes, also write to a file in the project folder
        // File.WriteAllBytes(Application.dataPath + "/../SavedScreen.png", bytes);

This piece of code takes a texture 2d class, converts it to bytes (just like you are already doing) and then writes it as binary using File.WriteAllBytes(). You should also destroy the texture object (Object.Destroy(Your texture)) to prevent the game from storing unnecessary bytes which might cause lag spikes from the garbage collector (I think).

But all of this is useless for you're case, if you want to screenshot the main camera you can just use unity's built in function, which also insures cross platform compatibility:

ScreenCapture.CaptureScreenshot("your path");

If you need an higher-res OR lower-res screenshot, add an multiplier argument after the path, like this:

ScreenCapture.CaptureScreenshot("your path", SizeMultiplier);

So, to wrap this up, do something like this and you should be good to go:

ScreenCapture.CaptureScreenshot(Application.dataPath + "/File.png");
Lila
  • 46
  • 1
  • 7
  • Thanks for your reply, The code you've shared it's creating JSON file but it's not in the form of JSON, JSON file having this type of characters: 'âPNG IHDR8ħp] IDATxÏΩÀñ‰ºÚ›W◊æ|ÁHiŸœÊ'‘O‚ôGxy‚ß≥§%À÷˘∫ªÓ˛ÌâA2 fiA&≤´3q DÏÿdíÙ˚ˇÈ˘flÓŒˇ¯Ì‚¯â&VSúhÇÿ° ' Please suggest me can I send this data to server. So I cannot send textures directly in web request and I need to convert it into basestring and the whole data needs to be converted as JSON. – Ali Hussain Sep 30 '21 at 08:26
  • The `[Serializable]` attribute is for **types** not for string variables / fields (? don't really understand where you say OP should add this) – derHugo Sep 30 '21 at 09:22
  • And you know btw that OP is already using `texture.EnciodeToPNG` in the original code ^^ – derHugo Sep 30 '21 at 09:24
  • To send textures via webrequest use binary data instead of string, you will have to use AddBinaryData. – Lila Sep 30 '21 at 11:47
  • @Lila Most problems were with conversion data to binary then to jSON, can you please show demonstration how to achieve this in an example actually I'm not experienced enough in it in C#, Unity. – Ali Hussain Oct 04 '21 at 07:45
1

I don't understand most of your code

like e.g. what is this line doing?

Application.ExternalCall("screenshot", System.Convert.ToBase64String(texture.EncodeToPNG()));

Is this supposed to be a callback of some sort? Seems like you encode some texture to a string and then never use that string for anything.

And then you use texture.EncodeToPNG again right after that which is pretty expensive.

Then you already get a string. So what is in your eyes supposed to be the outcome of

string serializedAbilites = JsonUtility.ToJson(TextureArray);

And finally you get the serializedAbilities but then anyway don't use it at all but rather write to the file

File.WriteAllText(Application.dataPath + "/File.json", TextureArray);

I guess what you rather would do to get a JSON would be simply wrapping this into a valid JSON object like e.g.

{
    "content" : "..........Your encoded string here ........."
}

So you could very easily achieve what you want to do by using

var json = "{\"content\":\"" + TextureArray + "\"}";
File.WriteAllText(Path.Combine(Application.dataPath, "File.json"), json);

Or alternatively have an actual wrapper class for your JSON layout like

[Serializable]
public class ImageJson
{
    public string content;
}

and then use

var imageJson = new ImageJson
{
    content = TextureArray 
};

var json = JsonUtility.ToJson(imageJson);
File.WriteAllText(Path.Combine(Application.dataPath, "File.json"), json);
derHugo
  • 83,094
  • 9
  • 75
  • 115