Native Image Examples


#1

I’m wanting to do some Canvas related projects but find little code samples or any real examples. The Official Native Image page is very vague, at least for newbie like me.

If anyone know any good working examples (with or without documentation) or any boilerplates etc would be awesome.

As best I can figure most of the HTML5 canvas code can work but the problem is when you go to save files. In canvas it seems easy enough just to force the browser to download a file or open a new window and send the data there. From there then you right click and “save file as”.

But I gather that Native Image does that equivalent function in Electron? Anyway a nudge in the right direction is greatly appreciated.

If it is possble to actually use the full OS or Windows “Explorer” file dialog that would be ideal, but based on what I read on the HTML5 canvas implementation I might just SOL on that, but I could live with a new Window pop-up with the image and then “Save As”.


#2

I might be misinterpreting what your saying, but I don’t think NativeImage is what you need.

From my experience with it it’s for setting and getting images in a format native to the the OS, so they can be used in a web-like way. For example, if I want to place an image of the user in the MenuBar (like Chrome does for signed in users), I’d use it for that. Similarly for using images from the clipboard, you’ve got a native implementation of an image and a web implementation of an image, and NativeImage is the bridge for this.

Maybe I’m wrong, and I’ve misunderstood what’s possible with NativeImage or your question.

On a side note, you can use the fs Node module to write to the file system, which sounds like it’ll at least be of some use to you.


#3

I think you are misinterpreting what I am saying.The “electron-canvas-to-buffer” for example show some methods and specifically mentions “Native Image” as what it uses.

Anyway, thanks but I’m looking for working example code from someone who actually has used it.


#4

I have used it, but not for what you’re using it for, hence why I’m not sure it’s what you want to do with it.

I can’t tell how electron-canvas-to-buffer gives an example of what you want to do, but I don’t think it’s as much of simple thing as you’re anticipating. In fact, from the sounds of it, electron-canvas-to-buffer sounds like what you should be using instead of NativeImage, unless you plan on rewriting the same code.

I still have no idea what you’re actually trying to do. It sounds as if electron-canvas-to-buffer does exactly what you need. First create a save dialog (https://github.com/atom/electron/blob/master/docs/api/dialog.md), then on the callback, use canvasBuffer to write to fs.

Either way, electron-canvas-to-buffer is a working example of NativeImage being used this way.


#5

If you can’t supply a link to a boilerplate or sample working application, or link to, then as much as i appreciate it, you are no help to me.

What I need is some code sample that can take a HTML5 canvas and save to a local file using electron.

I know how to do this in a normal browser, but not Electron,


#6

Ok, I’ve tried it, the snippet on the electron-canvas-to-buffer page works, just npm install electron-canvas-to-buffer --save:

var canvasBuffer = require('electron-canvas-to-buffer')
var fs = require('fs')

// your canvas drawing
var canvas = document.createElement('canvas')
var context = canvas.getContext('2d')
context.fillRect(0, 0, 50, 50)
context.fillStyle = 'red'
context.fillRect(50, 10, 30, 20)

// as a buffer
var buffer = canvasBuffer(canvas, 'image/png')

// write canvas to file
fs.writeFile('image.png', buffer, function (err) {
  throw err
})

Wrap that in a function and set it as a callback to this:

var dialog=require('remote').dialog; // this might be slightly different based on your Electron version
dialog.showSaveDialog({title:'Testing a save dialog'},yourCallbackHere);

The callback is passed the path where the user chooses to save the item. I’d actually advise using write(), not writeFile() here.

So all together:

var canvasBuffer = require('electron-canvas-to-buffer')
var fs = require('fs')
var dialog=require('remote').dialog; // this might be slightly different based on your Electron version

dialog.showSaveDialog({title:'Testing a save dialog',defaultPath:'/some/directory/here/image.png'},saveCallback);

function saveCallback(filePath){
// your canvas drawing
var canvas = document.createElement('canvas')
var context = canvas.getContext('2d')
context.fillRect(0, 0, 50, 50)
context.fillStyle = 'red'
context.fillRect(50, 10, 30, 20)
//or canvas=document.getElementsByTagName('canvas')[0], or whatever

// as a buffer
var buffer = canvasBuffer(canvas, 'image/png')

// write canvas to file
fs.writeFile(filePath, buffer, function (err) {
  if(err)throw err;else console.log('Write of',filePath,'was successful');
})
}

#7

And like I said before, if you don’t want to require('electron-canvas-to-buffer'), electron-canvas-to-buffer is a working example of using NativeImage from canvas, and the function’s right there:


#8

OK Thanks, that’s more what I was looking for!


#9

That was all cobbled together pretty quickly from the documentation, in fact much more of that was copy and pasted than handwritten.

It just goes to show how much of the information is already there for you.


#10

I have it working … but being new to this I’m not really getting the path thing correct, the code as you suggested does work, and thank you. But I’m fairly sure that since the “electron-canvas-to-buffer” is not internal to Electron then I can’t get it to work like all my other apps do in Electron.

Here is what I have been doing before for my apps

Make a copy of the Electron folder
Rename it something
Edit the files “index.html” and “main.js” then add any other js or image file/folders as need.
Click the “electron.exe” file in the newly renamed folder and it runs. Note that this is the first time I have used a “require” that is not built-in to Electron.

So here is what I am doing now, I can only get it to work if I drag my folder to the electron window now.

Using “Drag your app here to run it” from “Welcome to Electron 0.37.2” window (from clicking electron.exe)
Electron installed in E:\Electron\electron-v0.37.2-win32-ia32 and using the default installation the “default_app” directory in the electron install is now unchanged from the initial installation.

My app is located in a different directory “default_app” not inside E:\Electron\electron-v0.37.2-win32-ia32" and it’s contents
index.html
canvastest.js
main.js
package.json

these files are modified as you can see below.

The “Testing a save dialog” opens and will save the file “image.png written” and the script executes with console message

“Write of E:\Electron\electron-v0.37.2-win32-ia32\image.png was successful” (I am using using mainWindow.openDevTools(); in main.js )

The image.png is saved, however, file is forced to be saved in “E:\Electron\electron-v0.37.2-win32-ia32” directory even
if changing file path in file dialog. The name image.png will not be changed nor will it save anywhere else.
The “file save” dialog will let you type a new name and select a new directory and appear to work otherwise (no error message when saved),
but still saves to the E:\Electron\electron-v0.37.2-win32-ia32" anyway even if pointing elsewhere. The file is not presented in any other directory.

Electron-canvas-to-buffer is installed to path E:\Program Files\nodejs\node_modules\npm\node_modules\electron-canvas-to-buffer
and was installed using NPM

If I try and not “drag and drop” and just include my files for the app into the “default_app” folder inside E:\Electron\electron-v0.37.2-win32-ia32"
then I get a “Cannot find module” error as the console message amd the file is not saved. As I mentioned at the beginning this is how I used electron before.

Was convenient this way and I could using it “portable” on a flash drive on another computer etc.

I even tried putting a copy of “electron-canvas-to-buffer” folder in the “default_app” directory but still get the “Cannot find module”.

My apps code I setup the canvas first in the HTML file then call my script canvastest.js

INDEX.HTML***************** I had to alter the tags or it wouldn’t display here :slight_smile:

!DOCTYPE html
html lang="en"
head
/head
body
p test /p
canvas id=“canvas” width=“200” height=“100” style=“border:1px solid #000000;”
/canvas

script type="text/javascript"
var c = document.getElementById(“canvas”);
var ctx = c.getContext(“2d”);
tx.fillStyle = 'yellow’
ctx.fillRect(50, 10, 30, 20)
/script

script type=“text/javascript” src=“canvastest.js”>/script
/body
/html


canvastest.js
var fs = require(‘fs’);
var dialog=require(‘remote’).dialog; // this might be slightly different based on your Electron version
var canvasBuffer = require(‘electron-canvas-to-buffer’);

dialog.showSaveDialog({title:‘Testing a save dialog’,defaultPath:‘image.png’},saveCallback);

function saveCallback(filePath){

// as a buffer
var buffer = canvasBuffer(canvas, ‘image/png’)

// write canvas to file
fs.writeFile(‘image.png’, buffer, function (err) {
//throw err
if(err)throw err;else console.log(‘Write of’,filePath,‘was successful’);
})

}


MAIN.JS*************************
var app = require(‘app’); // Module to control application life.

var BrowserWindow = require(‘browser-window’); // Module to create native browser window.

// Report crashes to our server.

require(‘crash-reporter’).start();

// Keep a global reference of the window object, if you don’t, the window will

// be closed automatically when the javascript object is GCed.

var mainWindow = null;

// Quit when all windows are closed.

app.on(‘window-all-closed’, function() {

app.quit();

});

// This method will be called when Electron has done everything

// initialization and ready for creating browser windows.

app.on(‘ready’, function() {

// Create the browser window.

mainWindow = new BrowserWindow({width: 1000, height: 1000,

	'node-integration':true });

// and load the index.html of the app.

mainWindow.loadUrl(‘file://’ + __dirname + ‘/index.html’);

mainWindow.openDevTools();

// Emitted when the window is closed.

mainWindow.on(‘closed’, function() {

// Dereference the window object, usually you would store windows

// in an array if your app supports multi windows, this is the time

// when you should delete the corresponding element.

mainWindow = null;

});

});



#11

The file is always saving to that same route because you’re forcing ‘image.png’. In my example code, that saveCallback function has an argument of filePath which is being provided by the save dialog. Basically, you’re ignoring the returned value and hard-coding image.png, which is defaulting to the location the program is being run from.

As for the module not showing up, that’ll be because the program’s being run from somewhere where the electron-canvas-to-buffer module is installed to. Either you could take out all the JS files from that module’s repo and dump them in your app, or you could try installing it in the location your running from. I don’t really use Electron this way, I’ve got my app in a folder containing all of my work projects and then I’m using it on the command line like Electron folder/where/my/main/js/lives, and you’ll want to install the module in that folder.


#12

Thanks, I feel really dumb, the filePath was the problem, seems obvious now that you point it out. I can now name the file and place it anywhere I like.

I still have the path problem though “Cannot find module ‘electron-canvas-to-buffer’”. If I call it from the command like as you suggest (Windows 10) it still gives the same error as if I just double click the electron.exe icon.

As I mentioned I haven’t had any trouble just running my apps by setting up the main.js and index.html in this path structure

Electron App Root -electron.exe
-------------------------locales
-------------------------resources
--------------------------------------atom.asar
--------------------------------------default_app
-----------------------------------------------------index.htm
-----------------------------------------------------main.js

Note that this Electron App Root is always a copy of my folder E:\Electron\electron-v0.37.2-win32-ia32 where Electron is initially installed to. I keep the initial Electron install as is then make my “boilerplates” from copies of this.

I tried putting copies of the folder “electron-canvas-to-buffer” in all the paths above, it didn’t allow me to run electron.exe from my app folder.

I also copied the only .js file “index.js” from the “electron-canvas-to-buffer” folder and put it in the same folder as “main.js”. I then tried changing the “require” to “index.js”

I guess if I only needed this on my PC and didn’t want to distribute it anywhere this would be OK to just drag and drop, since it does work that way. But I have difficulty understanding being forced to have others install NPM and the “electron-canvas-to-buffer” module via NPM. I would think that we can just add to our distribution and the module exists in the local path of the electron.exe somewhere in the package I distribute and should work?

Only if I drag and drop the “default_app” folder from my app path detailed above onto a running session of of Electron from my original Electron folder installed to E:\Electron\electron-v0.37.2-win32-ia32

Here are screen shots of the boilerplate paths …

I’m sorry I’m not grasping this very well. I think I maybe got spoiled because all my other apps use “require” but are built-into Electron and this module is external?

Anyway thanks for the help, learning Electron concurrent with JS is challenging.


#13

Ah, I see the problem, when requiring electron-canvas-to-buffer, if it’s not an npm dependency, you’ll have to require the file from its location in your app, require('./electron-canvas-to-buffer/index.js'); should do the trick.


#14

Awesome, that nailed it! Thanks for patience helping a newbie out with the solution!


#15

Hi @caffiend,

My project use requirejs to load js dependencies. (it’s a desktop app without any backend server)
While electron-canvas-to-buffer seems to be a nodejs module.

How can I add it using requirejs?

Here is what I’ve tried:

  1. npm i electron-canvas-to-buffer --save
  2. Copy folder electron-canvas-to-buffer into ‘vendor’ folder (which will be loaded by requirejs)
  3. Reference it in define([…]);

But my electron app couldn’t load.

Do you have any idea why?
Thank you very much


#16

You shoudn’t need to use requirejs for it (and probably not any of your dependencies), just npm i electron-canvas-to-buffer --save in the root of your project, and then in your app require('electron-canvas-to-buffer')


#17

@caffiend: Thank you for replying this so fast.
But the thing is, I’m working on an “existing” project, which use requirejs.
It’s a electron desktop app (which use the same code as the web app, just remove everything related to backend).

That’s what makes me confused now.
Now I have nodejs module loader, and requirejs module loader


#18

I think the confusion here is my app is a client side js app. While require(‘electron-canvas-to-buffer’) is working with server side js app, right?


#19

There is no server side, but you do have direct access to Node, so you have access to require and can use that to pull in all your JS dependencies.

There are solutions for requireJS here: https://github.com/electron/electron/issues/355
Which is also echoed in the Electron FAQ here: https://electron.atom.io/docs/faq/#i-can-not-use-jqueryrequirejsmeteorangularjs-in-electron