Search Unity

Resolved How convert a string to a Texture2D?

Discussion in 'Scripting' started by Quasar47, Jun 7, 2022.

  1. Quasar47

    Quasar47

    Joined:
    Mar 24, 2017
    Posts:
    122
    Hello everyone,

    I have found a shader that displays the game scene as ASCII characters, including UIs. To do so, it divides the UV screen in equal slices and replaces each of these slices by a texture representing a char. For instance, a texture with a "&" on it will display "&" on objects with similar lighting.

    1.png

    The thing is, having to modify which textures are used is a pain right now. The textures' names are hardcoded in the script to use Resources.Load to access them, and modifying them would require an external app like Photoshop.

    What I would like to have is to assign strings directly in the Inpsector, then the code converts them into a texture2D with the same size as my previous textures. I have found a thread that explains how to convert a string to string64, then to a byte array, then to a Texture2D, but I couldn't find anything that worked. I don't think it would be possible to change the font either, so just the conversion would help me greatly.

    Here's what I have regarding the conversion:
    Code (CSharp):
    1.  
    2.             string str64 = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(strToDislay));
    3.             byte[] imageBytes = Convert.FromBase64String(str64);
    4.             Texture2D tex = new Texture2D((int)charSize.x, (int)charSize.y);
    5.             tex.LoadImage(imageBytes);
    Thanks for your help.
     
    Last edited: Jun 7, 2022
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,742
    When you say "convert" do you mean turn the string "R" into a graphic that looks like R ?

    If so, then use TextMesh or TextMeshPRO and a RenderTexture to "strike" each glyph in whatever font you want, point a camera at it and "photograph" it with the RenderTexture, and keep that texture for later use.

    Tons of RenderTexture examples out there, and they are used to basically capture what comes out of a camera.

    Here's a lotto scratcher example that uses RenderTextures:

     
  3. Quasar47

    Quasar47

    Joined:
    Mar 24, 2017
    Posts:
    122
    Hello, and thank you for your help. Unfortunately, this is not what I'm looking for, since I already have textures representing the caracters I want. What I want is to be able to change any of these caracters on the fly (or at least once at startup) so that I don't have to create a texture for each caracter I want in the game.

    I do not want to use these textures directly, I want to write a char in the Inspector, then let the code convert it into a Texture2D, like in the code sample I provided.
     
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,742
    You could just make a serializable class that contains the character and the corresponding texture:

    Code (csharp):
    1. [System.Serializable]
    2. public class StringToTexture2D
    3. {
    4.   public string str;
    5.   public Texture2D Texture
    6. }
    Now make an array of them:

    Code (csharp):
    1. public StringToTexture2D[] Lookups;
    and fill them all out in the inspector.

    At start up, iterate them and insert them into
    Dictionary<string,Texture2D>
    for high-speed access.
     
  5. Quasar47

    Quasar47

    Joined:
    Mar 24, 2017
    Posts:
    122
    It seems you've misunderstood what I am trying to achieve. What I want is to avoid having to setup any Texture from the Inspector or via Resources.Load (or any equivalent) altogether. The only Textures I want is from converting some chars into Textures. The reason for this is that I want to avoid having to use a texture atlas or to edit these textures in an external editor like Photoshop.

    If that's not possible, that's fine, atlases will have to do, but I would like to implement if it is the case.
     
  6. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,742
    If this is true:

    and you want this:

    then it seems you would need to use OCR (optical character recognition) on the textures to connect each texture to the right string / charactere.

    That is certainly doable, but certainly isn't trivial. I don't even know where you'd start.
     
  7. Quasar47

    Quasar47

    Joined:
    Mar 24, 2017
    Posts:
    122
    Thanks for the tip, I didnt know OCR was a thing, although it seems OCR does the opposite of what I want.
    I've just found this blog that seems to do the trick with any kind of font for my text, I'll give it a try tomorrow :
    http://blog.almostlogical.com/2010/...time-in-unity3d-without-using-render-texture/

    For now, I'll mark the thread as Solved until I come back tomorrow to output my results.
     
  8. Quasar47

    Quasar47

    Joined:
    Mar 24, 2017
    Posts:
    122
    Alright, so I couldn't get the resources to work at the link I provided. So instead of converting strings to textures, I found an ASCII spritesheet online and converted its sub-sprites instead. Not the result I expected, but at least I can use other symbols than just ASCII chars, so that's fine by me.

    The code :

    Code (CSharp):
    1.  
    2.         private Texture LoadTexture(Sprite sprite)
    3.         {
    4.  
    5.             Texture2D tex = new Texture2D((int)sprite.rect.width, (int)sprite.rect.height);
    6.             Color[] pixels = sprite.texture.GetPixels((int)sprite.textureRect.x,
    7.                                                     (int)sprite.textureRect.y,
    8.                                                     (int)sprite.textureRect.width,
    9.                                                     (int)sprite.textureRect.height);
    10.             tex.SetPixels(pixels);
    11.             tex.Apply();
    12.  
    13.             // safety, if forgotten when we added them
    14.             tex.wrapMode = TextureWrapMode.Repeat;
    15.             tex.filterMode = FilterMode.Point;
    16.             tex.hideFlags = HideFlags.HideAndDontSave;
    17.  
    18.             return tex;
    19.         }
    I'll still mark this thread as Resolved since I found a more effective way of doing the job, and I linked the other project in my previous comment in case anyone wants to try it.