Search code examples
c#unity-game-engineamazon-s3aws-sdkstreamreader

Load Image from Stream/StreamReader to Image OR RawImage component


I'm using AWS Unity (v3.3.50.0): S3 SDK (AWSSDK.S3.3.3.5.4.unitypackage) downloaded from https://aws.amazon.com/mobile/sdk/. My Unity version is 5.5.1.

I want to download an image placed on S3 bucket, bucket is configured and can be downloaded. And I see the string as data in response.

But I cannot able to convert the returned StreamReader to UnityEngine.UI.Image.sprite OR UnityEngine.UI.RawImage.texture in S3 sample GetObject() function.

private void GetObject()
{
    ResultText.text = string.Format("fetching {0} from bucket {1}", SampleFileName, S3BucketName);
    Client.GetObjectAsync(S3BucketName, SampleFileName, (responseObj) =>
        {
            string data = null;
            var response = responseObj.Response;
            if (response.ResponseStream != null)
            {
                using (StreamReader reader = new StreamReader(response.ResponseStream))
                {
                    data = reader.ReadToEnd();
                }

                ResultText.text += "\n";
                ResultText.text += data;
            }
            Debug.Log("GetObject: " + data);
        });
}

help required regarding this :)

Images on S3 bucket are in PNG format. But in future JPG, JPEG format support have to enable.


Solution

  • StreamReader is used for text not binary data like the image you want to download. I can tell why you are using it and can't also tell why you perform Debug.Log("GetObject: " + data); on an image.

    Download the image,then use Texture2D.LoadImage to convert it to Texture2D, you can then load that to your RawImage to display.

    public RawImage displayTexture;
    
    private void GetObject()
    {
        ResultText.text = string.Format("fetching {0} from bucket {1}", SampleFileName, S3BucketName);
        Client.GetObjectAsync(S3BucketName, SampleFileName, (responseObj) =>
        {
            byte[] data = null;
            var response = responseObj.Response;
            if (response.ResponseStream != null)
            {
                using (StreamReader reader = new StreamReader(response.ResponseStream))
                {
                    using (var memstream = new MemoryStream())
                    {
                        var buffer = new byte[512];
                        var bytesRead = default(int);
                        while ((bytesRead = reader.BaseStream.Read(buffer, 0, buffer.Length)) > 0)
                            memstream.Write(buffer, 0, bytesRead);
                        data = memstream.ToArray();
                    }
                }
    
                //Display Image
                displayTexture.texture = bytesToTexture2D(data);
            }
        });
    }
    
    public Texture2D bytesToTexture2D(byte[] imageBytes)
    {
        Texture2D tex = new Texture2D(2, 2);
        tex.LoadImage(imageBytes);
        return tex;
    }
    

    Like I mentioned above, using StreamReader is not good for binary data. You can just use MemoryStream to do that. In that case, your new GetObject function should look like this:

    private void GetObject()
    {
        ResultText.text = string.Format("fetching {0} from bucket {1}", SampleFileName, S3BucketName);
        Client.GetObjectAsync(S3BucketName, SampleFileName, (responseObj) =>
        {
            byte[] data = null;
            var response = responseObj.Response;
            Stream input = response.ResponseStream;
    
            if (response.ResponseStream != null)
            {
                byte[] buffer = new byte[16 * 1024];
                using (MemoryStream ms = new MemoryStream())
                {
                    int read;
                    while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
                    {
                        ms.Write(buffer, 0, read);
                    }
                    data = ms.ToArray();
                }
    
                //Display Image
                displayTexture.texture = bytesToTexture2D(data);
            }
        });
    }