I’m developing a plugin that downloads a image from a url and copies it to the clipboard.
Right now, I am able to download it’s Base64 binary, encode it to base64 string and display it in a tag.
However, when I try to copy it to the clipboard, I recieve this error:
JPM [error] Message: Error: Unable to decode data given in a valid image.
Stack:
exports.set@resource://gre/modules/commonjs/toolkit/loader.js → resource://gre/modules/commonjs/sdk/clipboard.js:165:15 @resource://gre/modules/commonjs/toolkit/loader.js → resource://snapit/index.js:285:3
emit@resource://gre/modules/commonjs/toolkit/loader.js → resource://gre/modules/commonjs/sdk/event/core.js:97:9
portEmit@resource://gre/modules/commonjs/toolkit/loader.js → resource://gre/modules/commonjs/sdk/content/sandbox.js:321:7
emit@resource://gre/modules/commonjs/toolkit/loader.js → resource://gre/modules/commonjs/sdk/event/core.js:97:9
onContentEvent/<@resource://gre/modules/commonjs/toolkit/loader.js → resource://gre/modules/commonjs/sdk/content/sandbox.js:362:5
delay/<@resource://gre/modules/commonjs/toolkit/loader.js → resource://gre/modules/commonjs/sdk/lang/functional/concurrent.js:38:20
notify@resource://gre/modules/commonjs/toolkit/loader.js → resource://gre/modules/commonjs/sdk/timers.js:40:9
I can’t tell what you did wrong without your code, but this is how I copy image from canvas to clipboard, probably not the best, as its using xpcom, i would love to just do it with arraybuffer’s and like canvas.to* async stuff:
//////// start helpers
// Create a constructor for the built-in transferable class
const nsTransferable = CC("@mozilla.org/widget/transferable;1", "nsITransferable");
// Create a wrapper to construct an nsITransferable instance and set its source to the given window, when necessary
function Transferable(source) {
var res = nsTransferable();
if ('init' in res) {
// When passed a Window object, find a suitable privacy context for it.
if (source instanceof Ci.nsIDOMWindow) {
// Note: in Gecko versions >16, you can import the PrivateBrowsingUtils.jsm module
// and use PrivateBrowsingUtils.privacyContextFromWindow(sourceWindow) instead
source = source.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIWebNavigation);
}
res.init(source);
}
return res;
}
/////// start copy to clipboardData
var data = this.canComp.toDataURL('image/png', '');
var channel = Services.io.newChannel(data, null, null);
var input = channel.open();
var imgTools = Cc['@mozilla.org/image/tools;1'].getService(Ci.imgITools);
var container = {};
imgTools.decodeImageData(input, channel.contentType, container);
var wrapped = Cc['@mozilla.org/supports-interface-pointer;1'].createInstance(Ci.nsISupportsInterfacePointer);
wrapped.data = container.value;
var trans = Transferable(this.gBrowserDOMWindow);
console.info('channel.contentType:', channel.contentType);
trans.addDataFlavor(channel.contentType);
trans.setTransferData(channel.contentType, wrapped, -1);
Services.clipboard.setData(trans, null, Services.clipboard.kGlobalClipboard);
I don’t think there is anything wrong with the code. I don’t think there is much wrong with the file, it is certainly readable by common image apps. There might be something unusual in the file that cannot be handled by this particular underlying library. The error message “Invalid flavor for image/jpg” suggests as much without really giving any useful information. One interesting thing about this image is that it was apparently created in the LAB color space, something which cannot be directly stored in a JPG. It is now stored in sRGB, but maybe still something else odd in there. Maybe the colour profile? I’ve seen this referred to as a “flavour” sometimes.