Base 64 Images

Hi,

I’m currently working on porting an app from Xamarin, and the underlying transport mechanism between the app and our DB is a webservice returning results in JSON. I’ve managed to successfully make the Fetch calls to our webservice to retrieve the JSON, but need to consume the images that are retrieved in a base64 format as part of the JSON result.

Is there a mechanism (whether JS or Uno) that I can use for handling base64 images instead of using a URL or filesource?

Thanks, Sean

We do not have built in support for this, but I hacked together a small sample for you to show how you could implement this yourself.

First add a package reference to Experimental.TextureLoader in your project file like this:

{
  "Packages": [
    "Fuse",
    "FuseJS",  	
    "Experimental.TextureLoader"
  ],
  "Includes": [ "*" ]
}

Then you need to create a custom ImageSource, in this case we get most of it free by inheriting TextureImageSource. This should be good enough to use as a starting point for you:

using Uno;
using Uno.Graphics;
using Uno.UX;
using Fuse.Resources;
using Experimental.TextureLoader;

public class Base64ImageSource : TextureImageSource
{
    void SetTexture(texture2D texture)
    {
        Texture = texture;
    }

    string _base64image;

    [UXContent]
    public string Base64
    {
        get { return _base64image; }
        set
        {
            if (_base64image != value && value != null)
            {
                _base64image = value;
                var stripped = _base64image.Replace("data:image/png;base64,", "").Replace("data:image/jpeg;base64,", "");
                var data = Uno.Text.Base64.GetBytes(stripped);

                try 
                {
                    if (_base64image.StartsWith("data:image/png"))
                        TextureLoader.PngByteArrayToTexture2D(new Buffer(data), SetTexture);
                    else if(_base64image.StartsWith("data:image/jpeg"))
                        TextureLoader.JpegByteArrayToTexture2D(new Buffer(data), SetTexture);
                }
                catch(Exception e)
                {
                    debug_log e.Message;
                }
            }
        }
    }
}

After that you can use your new ImageSource like this:

<App>
    <JavaScript>
        module.exports = {
            imageString : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAADaSURBVDhPtZK9CYRAFISvNhEUURDEwAIMLMAWLMHcxMDQMqzAxCIUxUSdY/f2+cfbC05u4Iuc+VjWfeFh/itYluUrIlpBURQwTVOL7/sYx5EX9H0Pz/NgWZaWqqpklxVkWcaOiDiOVZMRtG0L27bZIdE0jWrfBOu6IkkSdkSkaSp7lIugrmt2RARBgGEYVPuTXSA+uK7LDomyLFX7yC7I85wdEWEYYp5n1T4iBV3XwXEcdkicL+6cl3hRURTBMAwt4uLo5d0jTyCONk2Tlm3bZJnL5S/8kocC4A2RfkKIvwD9JQAAAABJRU5ErkJggg=="
        };
    </JavaScript>
    <Image>
        <Base64ImageSource Base64="{imageString}" />
    </Image>
</App>

That is awesome, I will it try it out.

Thanks!

I confirmed that it is working. I have some fuzziness with images that I also encountered w/ Xamarin. The solution I had for that issue on my Xamarin project was to use the UIImage ctor that had a scaling parameter: https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIImage_Class/index.html#//apple_ref/occ/clm/UIImage/imageWithCIImage:scale:orientation:

Is there anyway to do something similar here?

I’m guessing this is because the image comes in at one resolution and is displayed at another. Since the images in Fuse are rendered using a super fast and simple blit shader, I’m guessing the “fuzziness” is the result of hardware bilinear filtering. The UIImage ctor likely does some CPU downscaling with better filtering than the GPU provides, which is why specifying a scaling param in the ctor would make it look better.

The closest thing we have to a solution for this in Fuse currently is our MultiDensityImageSource, though it might not cover the case where the image resource itself isn’t known to the compiler, like you’re doing, unless you can serve the images in multiple resolutions from your server (and if you’re doing that, might as well just serve the resolution you need, which would probably fix the problem as well). It may be possible that we add upfront rescaling like the UIImage ctor seems to have to the Experimental.TextuureLoader class in the future, but as that’s experimental, it’s unfortunately not the highest priority right now. It might also be the case that we detect cases like these where we know GPU filtering might not look the best and prescale internally, but that’s a bit far-out timewise as well :slight_smile:

In the meantime, you can try to play with different StretchMode’s on the Image class and see if any of those look better.

Anders Bondehagen wrote:

We do not have built in support for this, but I hacked together a small sample for you to show how you could implement this yourself.

First add a package reference to Experimental.TextureLoader in your project file like this:

{
  "Packages": [
    "Fuse",
    "FuseJS",  	
    "Experimental.TextureLoader"
  ],
  "Includes": [ "*" ]
}

Then you need to create a custom ImageSource, in this case we get most of it free by inheriting TextureImageSource. This should be good enough to use as a starting point for you:

using Uno;
using Uno.Graphics;
using Uno.UX;
using Fuse.Resources;
using Experimental.TextureLoader;

public class Base64ImageSource : TextureImageSource
{
    void SetTexture(texture2D texture)
    {
        Texture = texture;
    }

    string _base64image;

    [UXContent]
    public string Base64
    {
        get { return _base64image; }
        set
        {
            if (_base64image != value && value != null)
            {
                _base64image = value;
                var stripped = _base64image.Replace("data:image/png;base64,", "").Replace("data:image/jpeg;base64,", "");
                var data = Uno.Text.Base64.GetBytes(stripped);

                try 
                {
                    if (_base64image.StartsWith("data:image/png"))
                        TextureLoader.PngByteArrayToTexture2D(new Buffer(data), SetTexture);
                    else if(_base64image.StartsWith("data:image/jpeg"))
                        TextureLoader.JpegByteArrayToTexture2D(new Buffer(data), SetTexture);
                }
                catch(Exception e)
                {
                    debug_log e.Message;
                }
            }
        }
    }
}

After that you can use your new ImageSource like this:

<App>
    <JavaScript>
        module.exports = {
            imageString : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAADaSURBVDhPtZK9CYRAFISvNhEUURDEwAIMLMAWLMHcxMDQMqzAxCIUxUSdY/f2+cfbC05u4Iuc+VjWfeFh/itYluUrIlpBURQwTVOL7/sYx5EX9H0Pz/NgWZaWqqpklxVkWcaOiDiOVZMRtG0L27bZIdE0jWrfBOu6IkkSdkSkaSp7lIugrmt2RARBgGEYVPuTXSA+uK7LDomyLFX7yC7I85wdEWEYYp5n1T4iBV3XwXEcdkicL+6cl3hRURTBMAwt4uLo5d0jTyCONk2Tlm3bZJnL5S/8kocC4A2RfkKIvwD9JQAAAABJRU5ErkJggg=="
        };
    </JavaScript>
    <Image>
        <Base64ImageSource Base64="{imageString}" />
    </Image>
</App>

Hi All,

Would this be the best approach to render an image coming from Java native code?

Context: Camera preview (using an adaptation of CameraPanel project to capture the frames without displaying them). Each frame is processed and should be displayed. So what we need is to render those natively processed frames.

Thanks in advance for your support,

Hi marcmelo8@gmail.com,
that is a different scenario, have you seen this? https://github.com/bolav/fuse-camerapanel
if that does not fit, please open a new thread with more details.

Anders Bondehagen wrote:

Hi marcmelo8@gmail.com,
that is a different scenario, have you seen this? https://github.com/bolav/fuse-camerapanel
if that does not fit, please open a new thread with more details.

Hi Anders and thanks for the reply.
Yes, actually we are using CameraPanel, but needed help on the rendering part (because the obtained frames are processed internally before rendering: AR).
I posted the full question here:

[(https://www.fusetools.com/community/forums/howto_discussions/render_dynamically_an_image_from_java_bitmap?page=1&highlight=c61e87b2-adcb-44f7-8559-50baf95bdf92#post-c61e87b2-adcb-44f7-8559-50baf95bdf92)]