Search Unity

How to convert a String[] to byte[]

Discussion in 'Scripting' started by blackant, Mar 29, 2022.

  1. blackant

    blackant

    Joined:
    Jun 18, 2009
    Posts:
    529
    Hi,

    I'm actually trying to make a conversion from image to byte, and then get the inverse from this byte[] to an image.

    My problem is that I get the data and I want to use it as a string to copy/paste it anywhere, but when I want to use this pasted string[] and convert it back to the image, I get an array size error, and don't figure how to solve it.

    Here is my code part:
    Code (CSharp):
    1. byte[] imgBytes = new byte[] { };
    2.  
    3.             string[] pastedString = ByteString.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
    4.            
    5.             for (int i = 0; i < pastedString.Length; i++)
    6.             {
    7.                  
    8.                 imgBytes[i] = (byte)int.Parse(pastedString[i]);
    9.                 Debug.Log("byte: " + pastedString[i] + " @ Index : " + i);
    10.             }
    11.             ByteToImage.LoadImage(imgBytes);
    12.            
    13.             ByteToImage.Apply();
    I tested a debug log before and after in the loop, and I correctly get the string value before trying to assigning it to the byte[]
    But get the error IndexOutOfRangeException: Index was outside the bounds of the array. At this step, and I'm only at index 0...
     
  2. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,478
    Code (CSharp):
    1. byte[] imgBytes = new byte[] { };
    You're asking why you cannot assign anything to this array? But it's empty. It's not some kind of resizable list, it's a fixed sized array and you create it with zero size.

    You'd need to create it with a size of "pastedString.Length".
     
  3. blackant

    blackant

    Joined:
    Jun 18, 2009
    Posts:
    529
    Ok, I fund this, my initiator was not good, so I modified this to:
    Code (CSharp):
    1. byte[] imgBytes = new byte[56];
    but now my problem is that it require a constant value for the size, which is not possible for this case, because i don't know which size the texture may be at first.


    With this fixed size I can get a texture, not the right one, because I get ?
    So I wonder what I missed.
     
  4. blackant

    blackant

    Joined:
    Jun 18, 2009
    Posts:
    529
    HO... i certainly did something wrong, i pasted back pastedString.Length to it and didn't get back the constant error alert...
     
  5. kdgalla

    kdgalla

    Joined:
    Mar 15, 2013
    Posts:
    4,637
    MelvMay already gave you the answer- Instead of 56, use pastedString.Length.

    Edit: Oops, looks like you already saw that.
     
  6. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,478
    You need to do something like this:
    Code (CSharp):
    1. using System.Collections.Generic;
    2. using UnityEngine;
    3.  
    4. public class ParseByteString : MonoBehaviour
    5. {
    6.     const string ByteString = "0, 128, 192, 255";
    7.  
    8.     void Start()
    9.     {
    10.         var pastedString = ByteString.Split(new string[] { "," }, System.StringSplitOptions.RemoveEmptyEntries);
    11.      
    12.         var imgBytes = new List<byte>(pastedString.Length);
    13.      
    14.         for(var i = 0; i < pastedString.Length; ++i)
    15.         {
    16.             imgBytes.Add(byte.Parse(pastedString[i]));
    17.         }
    18.  
    19.         var myByteArray = imgBytes.ToArray();
    20.     }
    21. }
    22.  
    Note: I'm parsing using a byte, not an int then casting it, not sure why you're doing that.
     
    dman8723 likes this.
  7. blackant

    blackant

    Joined:
    Jun 18, 2009
    Posts:
    529
    Lol, because I'm learning and I have seen this in another post somewhere ...:D

    Anyway, in a case or another, the result is still the same and I can only get the ? instead of the image.

    I attached a screenshot of my tool, so you can understand better what I try to achieve.
    I don't really get the point where it goes wrong, cause there is no error console except if I set a wrong options using format and extension
     

    Attached Files:

  8. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,478
    What do you mean the result is the same? It seems like you're now moving onto another problem without at least acknowledging that we've helped you fix the previous problem or if it's fixed at all.

    Bear in mind that nobody else can either because all we've seen is your initial rough bit of script.
     
  9. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,998
    Well, it's extremely unusual to write out a byte array as a comma seperated list of decimal encoded byte values. However you haven't really told us what those bytes even represent. Though just from looking at the few bytes we see in your screenshot we can already guess with high confidence that this does not represent any image file format but looks like just a list of RGB values. The LoadImage method of the Texture2D class can only load actual image formats like png or jpg. An image format also contains information about the size of the image. Your "string" looks like just a decimal converted list of RGB values. You can turn them into an array of Color32 values and turn that into an image. However your "string" does not contain any information about the size of the image.

    If your original image was 8x8 pixel it means you have 64 pixels and in turn results in 192 byte values, how should you know if the image is a 8x8, 4x16, 16x4, 32x2, ... image. So when you want to "export" an image as a byte array, you usually would use EncodeToPNG. You did not encode your image as png, otherwise we would see the png header at the beginning of your byte stream which we don't.

    So your whole generation of your string seems to be flawed already and it seems you don't really know what your byte array actually contains. So you may want to take a step back and rethink what you actually want to do.
     
  10. blackant

    blackant

    Joined:
    Jun 18, 2009
    Posts:
    529
    I mean the result is the same, because I tested many ways to get this byte[] and now that this is done, it is still not working....
    Using
    Code (CSharp):
    1. imgBytes[i] = Convert.ToByte(pastedString[i]);
    using
    Code (CSharp):
    1. imgBytes[i] = byte.Parse(pastedString[i]);
    or using
    Code (CSharp):
    1. imgBytes[i] = (byte)int.Parse(pastedString[i]);
    but I know the first problem to convert as been solved, thanks.
    But my objective is not reach.

    Thanks for your explications, it is more clear for me now, the string looks like an array of colors, I suppose other format I have seen 00x0032 or something like that is more byte related.

    But I want to use the data I get from the first code (the string list) to generate the same image in reverse. for now, and at this step, I will certainly not add more complexity width different sizes, there are already enough complexities to find a good way to get it to work.

    the first data was get using
    Code (CSharp):
    1. byte[] bArray = TextureImage.GetRawTextureData();
    2.             for (int i = 0; i< bArray.Length;i++)
    3.             {
    4.                 string t = bArray[i].ToString();
    5.                 TextResult += t + ",";
    6.             }
     
  11. blackant

    blackant

    Joined:
    Jun 18, 2009
    Posts:
    529
    I'm Still trying to understand the logic to use for this.

    What is the difference between using
    Code (CSharp):
    1. byte[] imgBytes = new byte[] { 82, 0, 0, 0, 250, 0, 0, 0, 40, 8, 6, 0, 0, 0, 215, 26, 231, 25, 0, 0, 16,};
    2. titleImage.LoadImage(ImgBytes);
    And using
    Code (CSharp):
    1. TextAsset tex;
    2. titleImage.LoadImage(Tex.bytes);
    because the first one method can work, and the second one can not this way.

    Also, I tried to create the image in photoshop, using int values as RGB colors, and I didn't reach the referenced image who gave me the string.
     
  12. blackant

    blackant

    Joined:
    Jun 18, 2009
    Posts:
    529
    I did another test, and this time I have a result, but not what I expected of course...
    This time I used
    Code (CSharp):
    1. ByteToImage.LoadRawTextureData(bArray);
    2. ByteToImage.Apply();
    to directly get Data from reference to instance, but well, something is wrong in the result, and i tested different formats, and every time get a different result.
    I made a Montage of it and noticed that the string is always different and for me doesn't give any clue about the way it is used to generate the texture.

    the string is not used and is only here for reading info, but doesn't really help.

    Code (CSharp):
    1. bArray = TextureImage.GetRawTextureData();
    2. for (int i = 0; i< bArray.Length;i++)
    3. {
    4.   string t = bArray[i].ToString();
    5.   TextResult += t + ",";
    6. }
    7. ByteToImage = new Texture2D(TextureImage.width, TextureImage.height,TextureImage.format,TextureImage.mipmapCount>1);
    8. ByteToImage.LoadRawTextureData(bArray);
    9. ByteToImage.Apply();
    10.  
     

    Attached Files: