Saving a PIXI.Sprite as a png without User input

standardplayer

Keeper of Kitties
Veteran
Joined
Apr 6, 2016
Messages
622
Reaction score
2,790
First Language
English
Primarily Uses
N/A
So I already know how to save a PIXI.Sprite to the local file directory, I use the following function

JavaScript:
sp_Tools.download_sprite_as_png = function(sprite, fileName) {

    let renderer = Graphics._renderer;

    renderer.extract.canvas(sprite).toBlob(function(b){

        var a = document.createElement('a');

        document.body.append(a);

        a.download = fileName;
        a.href = URL.createObjectURL(b);
        a.click();
        a.remove();

    }, 'image/png');

}
But this causes the file explorer to open.

The only current reason I have for needing this is because I've create a custom sprite maker, that lets you change clothes/hair, etc.
In the end, I have a single sprite. and I save that to the characters folder of img, in the proejct directory.
Then, I set that as the character name for the event or player. That all works fine.
I save it so I don't have to build the sprite every time, only when you need to change stuff. It's a LOT less work and loading.

But since some sprites can be created/altered in my project during execution, and this will be done by the user, I really don't want this file dialogue box to pop up.
(Obv I understand why the dialogue pops up, and the security reasons that also go behind letting the user know when a file is about to saved on their system, even in a program's directory at the program's request. I get it.)

Any ideas?
 

gstv87

Veteran
Veteran
Joined
Oct 20, 2015
Messages
2,148
Reaction score
1,115
First Language
Spanish
Primarily Uses
RMVXA
wild guess.... but, can't you use the file manager to write a variable to disk the same way you save a game, and then rename it to .png?

I mean, in the end it's all binary, the system shouldn't distinguish from game data or PNG color bits when writing said bits to disk.
 

standardplayer

Keeper of Kitties
Veteran
Joined
Apr 6, 2016
Messages
622
Reaction score
2,790
First Language
English
Primarily Uses
N/A
Nah, the file system uses JSON files to store the data, and stringifies the objects, which you can't do to a sprite or texture.
I'm starting to think I might have a way.
If I can't find one I have other methods, but being able to save the image stops me from having to do SO much other work
 

gstv87

Veteran
Veteran
Joined
Oct 20, 2015
Messages
2,148
Reaction score
1,115
First Language
Spanish
Primarily Uses
RMVXA
I'm not that well-versed in file managing in JS, but it looks like the conversion to JSON is internal.... meaning, the file manager still writes to disk in binary, except the bulk of bits is arranged as a JSON.

hard to explain without knowing the full details, but look into JS's own file management methods... it should work straight in binary, every time.
otherwise, there would be no point in using it anywhere, for anything, if it can't write to disk or at least pass the data to the operating system.

EDIT: in fact, I'm pretty sure there are plugins out there that output TXT files, and I believe I've seen a JS/Ruby converter that outputs RB.
granted, .RBs are text, but I mean the output can be controlled.
 

standardplayer

Keeper of Kitties
Veteran
Joined
Apr 6, 2016
Messages
622
Reaction score
2,790
First Language
English
Primarily Uses
N/A
Alright, so I've been researching around, and I wanted to do this the xhr way, rather than use the file system. However, I haven't found that.

I did, however, find how to do it with the file system. Now let me say, I don't know enough to tell if you this is the best way to do it, or all of the potential consequences. I just know that it does seem to work.

Now to do this with a sprite, I needed to get an appropriate data URL for the image. Since I'm constructing it during the game's execution, the sprite actually has a null value for it's .texture.baseTexture.imageUrl property. (If you'd loaded it as a complete image from elsewhere, it would have an address).

My hangup was on the base64 encoding, which I finally found an answer for here

I wrote the following function based off of what I found
JavaScript:
sp_Tools.saveImagePng = function(spr, fileName){
    let renderer = Graphics._renderer;
    let url = renderer.extract.canvas(spr).toDataURL('png', 100);
    let b64 = url.replace(/^data:image\/[a-z]+;base64,/, "");
    let fs = require('fs');
    fs.writeFile('img/spriteCon/' + fileName + '.png', b64, 'base64');
}
An example of this function being called with the path/filename to save with:
JavaScript:
sp_Tools.saveImagePng(mySprite, 'img/characters/myNewFileName');
 

gstv87

Veteran
Veteran
Joined
Oct 20, 2015
Messages
2,148
Reaction score
1,115
First Language
Spanish
Primarily Uses
RMVXA
Code:
fs.writeFile('img/spriteCon/' + fileName + '.png', b64, 'base64');
that's what I was looking for: basic write to disk.

if it exists (and it must, otherwise the language is pretty useless) then it can be called by other functions, including graphics.
it's all bits, and bits are universal.
 

standardplayer

Keeper of Kitties
Veteran
Joined
Apr 6, 2016
Messages
622
Reaction score
2,790
First Language
English
Primarily Uses
N/A
@gstv87 I've known about the .write/.writeFile functions of the fs for a while. I'd never dealt with the encoding, or with saving images with this method. I wanted a different solution, though. There's reasons why I don't want to use the file system. Without getting specific, let's just say it's more limiting in the end, as far as deployment, because there are platforms where the game doesn't access the user's file system.

There's other ways, hopefully someone can still enlighten me
 

caethyril

^_^
Veteran
Joined
Feb 21, 2018
Messages
1,660
Reaction score
1,111
First Language
EN
Primarily Uses
RMMV
One option might be to simply store it as a very simple .json file, e.g. the base-64 image data is the first element in a one-element array? I'm thinking you could then pass it through all the standard StorageManager methods and wouldn't have to worry about stuff like "does this image belong to this RPG Maker MV game". Then on load you just have to parse it from array to text to get the data URI before loading as normal. (ImageManager.loadNormalBitmap? I assume you've already figured out that part. :kaoslp:)

Otherwise...web-deployed games do not have access to the local file system, as you've said. In that case, save files are put in the browser's local storage. Here's an excerpt from rpg_managers.js for reference:
JavaScript:
StorageManager.saveToWebStorage = function(savefileId, json) {
    var key = this.webStorageKey(savefileId);
    var data = LZString.compressToBase64(json);
    localStorage.setItem(key, data);
};
So you need a key (filename) and some data, fairly simple. Then you need some way of making sure it doesn't interfere across games (cf DataManager.isThisGameFile), maybe some other stuff. Details on localStorage can be found here:
 

standardplayer

Keeper of Kitties
Veteran
Joined
Apr 6, 2016
Messages
622
Reaction score
2,790
First Language
English
Primarily Uses
N/A
@caethyril should have just @mentioned you in the first place ^^ Thank you for pointing this stuff out, I actually have tried passing an image to the save contents, the same way as rest of the save contents, but I got errors each time. I can't remember the code, something about 'circular' was in the code.

Either way the web storage bit may be what I need to look into, thanks!
 

caethyril

^_^
Veteran
Joined
Feb 21, 2018
Messages
1,660
Reaction score
1,111
First Language
EN
Primarily Uses
RMMV
Oh, a circular reference warning? That's weird. Did you remember to convert to a data URI (the base-64 thing) before trying to save? Maybe it's something to do with long strings in JSON...I think the StorageManager imposes a character limit or something. :kaoswt2:

I remember seeing a sketching plugin that stores images on Game_System (thus including them in the save file), might be a handy reference. Lemme go see if I can find a link...here!
 

standardplayer

Keeper of Kitties
Veteran
Joined
Apr 6, 2016
Messages
622
Reaction score
2,790
First Language
English
Primarily Uses
N/A
Did you remember to convert to a data URI (the base-64 thing) before trying to save?
Now that you mention it, when I had investigated this option, it was before I'd realized I'd need to have special encoding to save an image. It's possible that if I used the base64 encoded url from the canvas extraction, I'd be able to save it via JSON. Hopefully loading it wouldn't be any more complicated than loading anything else, but we'll see XD
 

Users Who Are Viewing This Thread (Users: 0, Guests: 1)

Latest Threads

Latest Profile Posts

Yo Ho Ho... Time flies when you are having rum...

I'm rewatching Glee, just watched grilled cheesus.
Now I'm not sure if I'm hungry or I want to cry.
I just completed Ara Fell - completing the game unlocks an Epilogue. An interesting thing to possibly consider for my games.
I decided to try to make a mucha-styled artwork, and by now I've sunk more time in studies and sketches than I usually do in the whole thing. Fingers crossed it's worth it!

Forum statistics

Threads
99,451
Messages
965,434
Members
131,067
Latest member
LeoWolf
Top