HTML5 Any way to load a base64-encoded image as a sprite?

Filipp_BSG

Member
I want to let user to load an image into the game via file select dialog. In JavaScript this is done by using the standart FileAPI, which can return a string representing the loaded image encoded in base64 like this:
Code:
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAACE8AAAalCAYAAADE...
The question is how to convert this string to image inside GM:S. I tried directly passing it to sprite_add as the first argument, using buffer_load/buffer_read/buffer_base64_decode combinations before passing, but no result. AFAIK, buffer functions won't work porperly with buffers created outside of GM:S. I see two really lame workarounds:
  • Upload image to server, then load it back via http_get_file and sprite_add;
  • Create an <img> element and manipulate it via JS, which is only suitable when the image is going to be (almost) static, which is not my case.
Thanks in advance if you know how to solve this problem.
 
Last edited:

meseta

Member
sprite_add takes a filename, not a buffer. You would have to buffer_save the decoded buffer as a file, and then load it using sprite_add. So the steps would be:
  1. clip off the data:image/png;base64, part of it, leaving just the base64-encoded raw image data
  2. use buffer_base64_decode on it to create a new decode buffer. This buffer now contains the png file
  3. buffer_save
  4. sprite_add
The only other option for getting from data into sprites is via buffer_set_surface and then sprite_create_from_surface. But you'd then need to do that PNG conversion. It might look something like this:
  1. Use extension to convert image to a GM BGRA buffer
  2. use buffer_set_surface to cast the buffer to a surface
  3. use sprite_create_from_surface
If formatted correctly, buffer data from outside GM should work fine. For example, I use the above method, but with nodejs code running on a cloud server that GM can send the URL of an image to, and receive a compressed BGRA buffer containing the image data that can then be set to a surface and turned into a sprite. This system allows GM to load in a image from anywhere on the internet (including animated GIFs) without having to do any file format conversion in GM itself, and in a way that should be easy to make cross-platform. This entire system relies on javascript being able to create a zlib compressed buffer that's fully compatible with GM buffers and GM's new buffer_decompress.
 
Last edited:

Filipp_BSG

Member
  • clip off the data:image/png;base64, part of it, leaving just the base64-encoded raw image data
  • use buffer_base64_decode on it to create a new decode buffer. This buffer now contains the png file
  • buffer_save
  • sprite_add
It works on windows but fails when compiled to HTML5. I'm using the following code:
Code:
var str="data:image/png;base64,...";
str=string_replace_all(str,"data:image/png;base64,","");
var buff=buffer_base64_decode(str);
buffer_save(buff,working_directory+"userImage.png");
spr_userimage=sprite_add(working_directory+"userImage.png",0,0,0,0,0);
buffer_delete(buff);
It searches for the file in game's default directory (html5game) and returns 404. I tried it without working_directory with the same result.
 

meseta

Member
Ok, that seems like an HTML5 save file issue. Unfortunately, I'm no experience with it, I hope someone else can help here.

For a quick test: if you save the png file on Windows, and include it as an Included File resource, can you get HTML5 to load that file? If that works, then it would mean the code itself works, but just the file save/load part has issues.
 

Filipp_BSG

Member
For a quick test: if you save the png file on Windows, and include it as an Included File resource, can you get HTML5 to load that file? If that works, then it would mean the code itself works, but just the file save/load part has issues.
Yes, no problem with loading files added to included before.
 
N

Nathan Archer

Guest
I want to let user to load an image into the game via file select dialog. In JavaScript this is done by using the standart FileAPI, which can return a string representing the loaded image encoded in base64 like this:
Code:
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAACE8AAAalCAYAAADE...
The question is how to convert this string to image inside GM:S. I tried directly passing it to sprite_add as the first argument, using buffer_load/buffer_read/buffer_base64_decode combinations before passing, but no result. AFAIK, buffer functions won't work porperly with buffers created outside of GM:S. I see two really lame workarounds:
  • Upload image to server, then load it back via http_get_file and sprite_add;
  • Create an <img> element and manipulate it via JS, which is only suitable when the image is going to be (almost) static, which is not my case.
Thanks in advance if you know how to solve this problem.
Did you ever figure this out? I'm currently struggling with the same problem.
 
D

dannyjenn

Guest
I'm not familiar with the base64 format, but you could probably write some code which will parse the base64 string and render the sprite pixel-by-pixel on a surface. Then you'd use sprite_create_from_surface() etc. in order to make the actual sprite. (A game I'm working on does something similar to this, though my game uses 2bpp Game Boy tile data rather than base64, and I just use surface_draw_part() instead of sprites.)
 
Top