LoadImage do not load from the web (target: html5)

Monkey Forums/Monkey Bug Reports/LoadImage do not load from the web (target: html5)

David Casual Box(Posted 2013) [#1]
According to the documentation, LoadImage is able to load an image from the web, using a resource path starting with http://.

Example:
myImage = LoadImage("http://www.laboutiqueofficielle.com/media/NBA/batman.jpg")

Here is what the documentation says regarding resource paths. The html5 target is mentioned supporting web and data.

Supported resource path prefixes

web = http://, https://
data = monkey://data/
file = monkey://internal/
Function Html5 Flash Glfw Android iOS XNA PSM
LoadString web, data data data, file web, data, file data, file data data
LoadImage web, data data data, file web, data, file web, data, file data data
LoadSound web, data data data, file data data, file data data
PlayMusic web, data data data, file data data, file data data
DataBuffer.Load web, data data data, file web, data, file data, file data data
FileStream.Open N/A N/A file file file file file


marksibly(Posted 2013) [#2]
The issue here is that html5 does its image loading asynchronously, so code like this...

Local image:=LoadImage(...)
Local w:=image.Width...

...may have problems if image isn't loaded by the time you want to to 'use' it (in this case, read it's width).

Monkey for html5 gets around this by preprocessing all images in your data dir when a project is built, and creating a little 'image info' DB which gets hardcoded into the output code.

Other targets have similar/different issues that require data to be pre-processed in some way (eg: xna can't read png/jpg, only 'preprocessed' data).

In general, Monkey is *designed* to work with a static set of data items. This allows it to preprocess stuff where necessary and 'fake' synchronous operations on targets that don't really support it (html5, flash).

You can, however, use the new async image loaders to load images from more sources, eg:

Import mojo

Class MyApp Extends App Implements IOnLoadImageComplete

	Field image:Image

	Method OnCreate()
		LoadImageAsync( "http://www.monkeycoder.co.nz/img/logo/cute/monkey1.png",,,Self )
		SetUpdateRate 60
	End
	
	Method OnUpdate()
		UpdateAsyncEvents
	End
	
	Method OnRender()
		Cls
		DrawText "Hello World!",0,0
		If image DrawImage image,DeviceWidth/2,DeviceHeight/2
	End
	
	Method OnLoadImageComplete:Void( image:Image,path:String,source:IAsyncEventSource )
		If image Print "OK!" Else Print "ERR"
		Self.image=image
	End

End

Function Main()
	New MyApp
End



David Casual Box(Posted 2013) [#3]
Amazing, it's work well! So Monkey support external images :)

Just to mention: monkey cannot draw an external image with a SetColor.

Example (change in your example):
SetColor 255,0,0
If image DrawImage image,DeviceWidth/2,DeviceHeight/2

Error Chrome:
Monkey Runtime Error : Error: SecurityError: DOM Exception 18
/Applications/MonkeyPro69/modules/mojo/graphics.monkey<445>
/Users/dmekersa/Dropbox/MonkeyWork/Async/main.monkey<20>
/Applications/MonkeyPro69/modules/mojo/app.monkey<67>


David Casual Box(Posted 2013) [#4]
Additionally,
Drawing a picture loaded asynchronously will make ReadPixel to crash with DOM Exception 18 too.


marksibly(Posted 2013) [#5]
These are all limitations of javascript/DOM.

Basically, you can't access the pixels of any image loaded 'cross domain', so drawing colored images fails since Monkey can't access the pixels in order to 'colorize' them (canvas oddly doesn't natively support drawing colored images so Monkey needs to fake it), and drawing an image 'taints' the canvas to prevent you cheating and reading image pixels indirectly from the canvas.

You may be able to configure the source image server to fix this (if you have access to it of course) but, in general, there's not anything Monkey programs can do about all this beyond avoiding drawing colored images and using ReadPixels when dealing with cross domain images.


David Casual Box(Posted 2013) [#6]
Gasp :) Thanks Mark.
Our aim was to "capture" a leaderboard we draw that include Facebook pictures. So, no, I don't have access to the server (or I can ask Mark Zuckerberg :)).
We'll try something: draw the leaderboard and then do not update it during the phase we wanted it to be a capture (to reduce draw calls), and use a limited DrawRect instead of Cls to keep it visible.