Search code examples
javascriptcanvasfirefox-addonxpcom

Stream canvas to imgITools to make ico


So on WinXP I have been having a hard time converting a PNG file to an ICO with canvas. I found this method encodeImage. I don't know if it works but it looks promising but I can't figure out how to feed the image I drew on a canvas into imgITools.decodeData.

What should I use for aImageStream and/or aMimeType?

imgTools.decodeImageData(aImageStream, aMimeType, imgContainer);

This is more of my code:

 img['asdf'].file = new FileUtils.File(myPathHere);

let iconStream;
try {
  let imgTools = Cc["@mozilla.org/image/tools;1"]
                    .createInstance(Ci.imgITools);
  let imgContainer = { value: null };

  imgTools.decodeImageData(aImageStream, aMimeType, imgContainer);
  iconStream = imgTools.encodeImage(imgContainer.value,
                                    "image/vnd.microsoft.icon",
                                    "format=bmp;bpp=32");
} catch (e) {
  alert('failure converting icon ' + e)
  throw("processIcon - Failure converting icon (" + e + ")");
}

let outputStream = FileUtils.openSafeFileOutputStream(img['asdf'].file);
NetUtil.asyncCopy(iconStream, outStream, netutilCallback);

Solution

  • Since you're having a canvas already(?), it would be probably easier to use either on of the following canvas methods:

    • toDataURI/toDataURIHD
    • toBlob/toBlobHD
    • mozFetchAsStream

    There is also the undocumented -moz-parse-options:, e.g -moz-parse-options:format=bmp;bpp=32. (ref-tests seem to depend on it, so it isn't going away anytime soon I'd think).

    So, here is an example for loading stuff into an ArrayBuffer.

    (canvas.toBlobHD || canvas.toBlob).call(canvas, function (b) {
        var r = new FileReader();
        r.onloadend = function () {
            // r.result contains the ArrayBuffer.
        };
        r.readAsArrayBuffer(b);
    }, "image/vnd.microsoft.icon", "-moz-parse-options:format=bmp;bpp=32");
    

    Here is a more complete example fiddle creating a 256x256 BMP icon.

    Since you likely want to feed that data into js-ctypes, having an ArrayBuffer is great because you can create pointers from it directly, or write it to a file using OS.File.