Create image from UX Panel

Creating a Image from UX Panels in JS? (like a screenshot i suppose)

Hi, I have made an API for that, you can find it on github:

Use MainView.ux as the reference to how the API is used. It supports iOS, macOS, Windows and Android.

sweet ill have a look :smiley:

Hi Emil theres a error when compiling for iOS

CapturePanel.uno(91.13): E3107: 'JpegSaver' does not contain a member called 'ByteArrayRgbaToJpeg'. Could you be missing a package reference?
/CapturePanel.uno(91,14,91,33): Error E3107: 'JpegSaver' does not contain a member called 'ByteArrayRgbaToJpeg'. Could you be missing a package reference?

Hi it seems to work in iOS now :smiley: one last question, when using ImageTools:

function capture() {
  capturePanel.capture(function(file) {
    capturedImg.value = file;
	ImageTools.getBase64FromImage(file).then(function(base64Image) { console.log("The base64 encoded image is \"" + base64Image + "\""); });
  });
}; 

I’m getting this error :

  LOG: /private/var/mobile/Containers/Data/Application/329CC89F-2356-409B-B8C3-69DBAD099E4D/tmp/579DDAF6-88AD-4F4F-8203-24CA6FCE3E9A-2742-0000024B8D5D8024.jpg

  LOG: Fuse.Scripting.ScriptException: 
         at Fuse.Scripting.JavaScriptCore.Context.OnError(Fuse.Scripting.JavaScriptCore.JSValueRef)
         at Fuse.Scripting.JavaScriptCore.JSObjectRef.CallAsFunction(Fuse.Scripting.JavaScriptCore.JSContextRef,Fuse.Scripting.JavaScriptCore.JSObjectRef,Fuse.Scripting.JavaScriptCore.JSValueRef[],Uno.Action<Fuse.Scripting.JavaScriptCore.JSValueRef>)
         at Fuse.Scripting.JavaScriptCore.Function.Call(object[])
         at CapturePanel.Draw(Fuse.DrawContext)
         at Fuse.Elements.Element.DrawNonUnderlayChildren(Fuse.DrawContext)
         at Fuse.Elements.Element.DrawWithChildren(Fuse.DrawContext)
         at Fuse.Elements.Element.CompositEffects(Fuse.DrawContext)
         at Fuse.Elements.Element.Composit(Fuse.DrawContext)
         at Fuse.Elements.Element.Draw(Fuse.DrawContext)
         at Fuse.Elements.Element.DrawNonUnderlayChildren(Fuse.DrawContext)
         at Fuse.Elements.Element.DrawWithChildren(Fuse.DrawContext)
         at Fuse.Elements.Element.CompositEffects(Fuse.DrawContext)
         at Fuse.Elements.Element.Composit(Fuse.DrawContext)
         at Fuse.Elements.Element.Draw(Fuse.DrawContext)
         at Fuse.Elements.Element.DrawNonUnderlayChildren(Fuse.DrawContext)
         at Fuse.Elements.Element.DrawWithChildren(Fuse.DrawContext)
         at Fuse.Elements.Element.CompositEffects(Fuse.DrawContext)
         at Fuse.Elements.Element.Composit(Fuse.DrawContext)
         at Fuse.Elements.Element.Draw(Fuse.DrawContext)
         at Fuse.Elements.Element.DrawNonUnderlayChildren(Fuse.DrawContext)
         at Fuse.Elements.Element.DrawWithChildren(Fuse.DrawContext)
         at Fuse.Controls.GraphicsView.DrawWithChildren(Fuse.DrawContext)
         at Fuse.Elements.Element.CompositEffects(Fuse.DrawContext)
         at Fuse.Elements.Element.Composit(Fuse.DrawContext)
         at Fuse.Elements.Element.Draw(Fuse.DrawContext)
         at Fuse.Controls.GraphicsView.DrawFrame()
         at Fuse.UpdateListener.Invoke()
         at Fuse.UpdateManager.Update(Fuse.Stage)
         at Fuse.UpdateManager.Update()
         at Fuse.AppBase.OnUpdate()
         at Fuse.App.OnUpdate()
         at Outracks.Simulator.Application.OnUpdate()
         at Fuse.App.OnTick(object,Uno.Platform.TimerEventArgs)
         at Uno.Platform2.Display.OnTick(Uno.Platform.TimerEventArgs)
      Name: TypeError
      Error message: null is not an object (evaluating 'ImageTools.getBase64FromImage(file).then')
      File name: MainView.js
      Line number: 1007
      JS stack trace: MainView.js:1007:40
      
  LOG: Detach
  LOG: Stop
  ERROR: 
      Name: TypeError
      Error message: null is not an object (evaluating 'ImageTools.getBase64FromImage(file).then')
      File name: MainView.js
      Line number: 1007
      JS stack trace: MainView.js:1007:40

Hi, I have updated the repo with a potential fix. I believe it was related to dispatching the JS callback on the wrong thread.

Hi im still getting this error

Fuse.Scripting.ScriptException: 
   at Fuse.Scripting.JavaScriptCore.Context.OnError(Fuse.Scripting.JavaScriptCore.JSValueRef)
   at Fuse.Scripting.JavaScriptCore.JSObjectRef.CallAsFunction(Fuse.Scripting.JavaScriptCore.JSContextRef,Fuse.Scripting.JavaScriptCore.JSObjectRef,Fuse.Scripting.JavaScriptCore.JSValueRef[],Uno.Action<Fuse.Scripting.JavaScriptCore.JSValueRef>)
   at Fuse.Scripting.JavaScriptCore.Function.Call(object[])
   at CallJSClosure.RunInternal()
   at Fuse.Reactive.ThreadWorker.RunInner()
   at Fuse.Reactive.ThreadWorker.Run()
   at Uno.Threading.POSIXThread.ReleasingLauncher.Run()
Name: TypeError
Error message: null is not an object (evaluating 'ImageTools.getBase64FromImage(file).then')
File name: MainView.js
Line number: 1011
JS stack trace: MainView.js:1011:40

when trying to use ImageTools on the file ps its definitely capturing as it displays the img after, but getting a Base64 string seems to be a problem…

var capturedImg = Observable();
function capture() {

capturePanel.capture(function(file) {
  ImageTools.getBase64FromImage(file).then(function(base64Image) { console.log("The base64 encoded image is \"" + base64Image + "\""); });
  //debug_log(file);
  capturedImg.value = file;
});
};

What does it say if you do

capturePanel.capture(function(file) {
  console.dir(file);
};

LOG: “/private/var/mobile/Containers/Data/Application/FE2CE687-A689-42F2-8D4B-9564C67C5B01/tmp/A1971CD4-2FAF-4A06-9E5E-FD52824EE107-4710-0000037304EADAF3.jpg”

What’s happens if you call:

ImageTools.getBase64FromImage(file)
.then(function(base64Image) { console.log("The base64 encoded image is \"" + base64Image + "\"");
}).catch(function(e) 
{
   debug_log("An error occured: " + e);
});

on ios fuse preview :

	Fuse.Scripting.ScriptException: 
	   at Fuse.Scripting.JavaScriptCore.Context.OnError(Fuse.Scripting.JavaScriptCore.JSValueRef)
	   at Fuse.Scripting.JavaScriptCore.JSObjectRef.CallAsFunction(Fuse.Scripting.JavaScriptCore.JSContextRef,Fuse.Scripting.JavaScriptCore.JSObjectRef,Fuse.Scripting.JavaScriptCore.JSValueRef[],Uno.Action<Fuse.Scripting.JavaScriptCore.JSValueRef>)
	   at Fuse.Scripting.JavaScriptCore.Function.Call(object[])
	   at CallJSClosure.RunInternal()
	   at Fuse.Reactive.ThreadWorker.RunInner()
	   at Fuse.Reactive.ThreadWorker.Run()
	   at Uno.Threading.POSIXThread.ReleasingLauncher.Run()
	Name: TypeError
	Error message: null is not an object (evaluating 'ImageTools.getBase64FromImage(file)
	      .then')
	File name: MainView.js
	Line number: 1017
	JS stack trace: MainView.js:1017:42

on ios debug :

	Fuse.Scripting.ScriptException: 
	Name: TypeError
	Error message: null is not an object (evaluating 'ImageTools.getBase64FromImage(file)
	      .then')
	File name: MainView.js
	Line number: 1017
	JS stack trace: MainView.js:1017:42

ImageTools.getBase64FromImage expects the first parameter to be a File object as

{
   name: "MyImage",
   path: "[somepath]"
}

In other words, please try to do the following

ImageTools.getBase64FromImage({ path: file, name: "Some random name" })
.then(function(base64Image) { console.log("The base64 encoded image is \"" + base64Image + "\"");
}).catch(function(e) 
{
   debug_log("An error occured: " + e);
});

Emil sweet this works although i did needed to clean the string up a bit :

    ImageTools.getBase64FromImage({ path: file, name: "Some random name" })
    .then(function(base64Image) { 

        fixString = base64Image.replace(/(\r\n|\n|\r)/gm,"");
        console.log("The fixed base64 encoded image is \"" + fixString + "\"");

    }).catch(function(e) 
    {
       debug_log("An error occured: " + e);
    });

Good :slight_smile:

android: 6
iOS: 10.3.3
fuse: 1.6

Hey guys, I’m getting the following error with the CapturePanel when exporting to android or iOS device, only happened after updating to fuse 1.6:

Projects/CapturePanel/CapturePanel.uno(26.12): E3104: Fuse.Scripting.Context does not contain a member called 'Dispatcher'. Could you be missing a package reference?

update CapturePanel.uno

public void Run(object arg)
{	
	_arg = arg;
	//_context.Dispatcher.Invoke(RunInternal);
}

Thanks Kevin but what did the commented out code do? Did you also get this afterwards:

Projects/CapturePanel/CapturePanel.uno(40.46): W4139: 'Fuse.Scripting.ScriptMethod`1..ctor(string,Uno.Action<Fuse.Scripting.Context, T, object[]>,Fuse.Scripting.ExecutionThread)' is obsolete: 'Use ScriptMethod<T>(string, Uno.Action<T)>), ScriptMethod<T>(string, Uno.Action<T, object[])>) or ScriptMethod<T>(string, Uno.Func<Fuse.Scripting.Context, T, object[], object)>) instead'

Hi,
Replace _context.Dispatcher.Invoke(RunInternal); with _context.Invoke(RunInternal) and see if that helps. Also, I think you can ignore the obsolete warning for now.

Just tried it but got this:

Projects/CapturePanel/CapturePanel.uno(26.12): E3128: Call to 'Fuse.Scripting.Context.Invoke(Uno.Action<Fuse.Scripting.Context>)' has some invalid arguments (<method_group>)

Does it do the same thing if I take what’s inside RunInternal() and place it in the Run(object arg) Emil?

        object _arg;
	public void Run(object arg)
	{	
		_arg = arg;
		//_context.Dispatcher.Invoke(RunInternal);
		_func.Call(_context,_arg);
	}
	
	void RunInternal()
	{
		_func.Call(_context,_arg);
	}