My goal is to make a .ico
or a HICON
out of canvas drawing. Below is a snippet for windows. What it does is lets you file pick. You pick an image and then it adds canvas to the document in current tab (at way bottom) and then draws the 32px logo on cavas and then on that it overlays the browsed image. Now im trying to us jsctypes of winapi CreateIconFromResourceEx
with canvas.mozFetchAsStream
but I can't figure it out.
I'm stuck on this line: alert(streamData)
.
Also for PBYTE
in my CreateIconFromResourceEx
is it correct to set it to ctypes.unsigned_char.ptr
? (Because byte I know is just ctypes.unsigned_char
right?)
Components.utils.import('resource://gre/modules/ctypes.jsm');
var user32 = ctypes.open('user32.dll');
/* http://msdn.microsoft.com/en-us/library/windows/desktop/ms648061%28v=vs.85%29.aspx
* HICON WINAPI CreateIconFromResourceEx(
* __in_ PBYTE pbIconBits,
* __in_ DWORD cbIconBits,
* __in_ BOOL fIcon,
* __in_ DWORD dwVersion,
* __in_ int cxDesired,
* __in_ int cyDesired,
* __in_ UINT uFlags
* );
*/
var CreateIconFromResourceEx = user32.declare('CreateIconFromResourceEx', ctypes.winapi_abi, ctypes.voidptr_t,
ctypes.unsigned_char.ptr, /* PBYTE pbIconBits */
ctypes.unsigned_long, /* DWORD cbIconBits */
ctypes.bool, /* BOOL fIcon */
ctypes.unsigned_long, /* DWORD dwVersion */
ctypes.int, /* int cxDesired */
ctypes.int, /* int cyDesired */
ctypes.unsigned_int /* UINT uFlags */
);
/////////////// running stuff below. above was just defining stuff
var me = Services.wm.getMostRecentWindow(null);
var canvas = document.createElementNS('http://www.w3.org/1999/xhtml', 'canvas');
var ctx = canvas.getContext('2d');
gBrowser.contentDocument.documentElement.appendChild(canvas);
var fp = Cc['@mozilla.org/filepicker;1'].createInstance(Ci.nsIFilePicker);
fp.init(window, 'Select Badge Image', Ci.nsIFilePicker.modeOpen);
fp.appendFilters(Ci.nsIFilePicker.filterAll | Ci.nsIFilePicker.filterText);
var rv = fp.show();
if (rv == Ci.nsIFilePicker.returnOK || rv == Ci.nsIFilePicker.returnReplace) {
var file = fp.file;
// Get the path as string. Note that you usually won't
// need to work with the string paths.
var path = fp.file.path;
var oImage = new Image();
oImage.src = 'chrome://branding/content/icon32.png'; //Services.io.newFileURI(file).spec;
oImage.onload = function() {
alert('loaded')
canvas.width = this.width;
canvas.height = this.height;
ctx.clearRect(0, 0, this.width, this.height);
ctx.drawImage(this, 0, 0);
var oImage = new Image();
oImage.src = Services.io.newFileURI(file).spec;
oImage.onload = function() {
alert('loaded')
ctx.drawImage(this, canvas.width-this.width, canvas.height-this.width);
//mozFetchAsStream stuff: https://github.com/mozilla/build-partner-repacks/blob/885947b726c5d6e131af4e4aae621d51109bded4/partners/yandex-drp/distribution/extensions/vb%40yandex.ru/cbapp/parts/screenshotsGrabber.js#L295
var asyncStreamCallback = {
onInputStreamReady: function (streamData) {
alert(streamData)
},
QueryInterface: XPCOMUtils.generateQI([
Ci.nsISupports,
Ci.nsIInputStreamCallback
])
};
canvas.mozFetchAsStream(asyncStreamCallback, 'image/vnd.microsoft.icon')
//now do canvas.mozGetAFile(blob) then reconstruct icon
}
}
}
////////////////
user32.close();
I don't know what's wrong with your code. But since your objective is to turn the canvas contents to an ICO, here is another way (somewaht more straightfoward I dare to say).
// assuming ctx holds your drawings
let imgdata = ctx.getImageData(0,0,32,32); // this is a 32x32 icon, right?
let icoencoder = Cc["@mozilla.org/image/encoder;2?type=image/vnd.microsoft.icon"].createInstance(Ci.imgIEncoder);
icoencoder.initFromData(imgdata.data, imgdata.data.length, 32, 32, 32*4, Ci.imgIEncoder.INPUT_FORMAT_RGBA, "");
icoencoder.QueryInterface(Ci.nsIInputStream);
var icofile = new FileUtils.File("/path/to/canvas.ico");
var output = FileUtils.openSafeFileOutputStream(icofile);
NetUtil.asyncCopy(icoencoder, output, youroptionalcallback);
The result is a proper canvas.ico
file which you can pass to the windows api functions.