In my Greasemonkey script, when I obtain a handle on an HTMLImageElement I want to use with an HTML Canvas, I get the following error in Firefox's Error Console (I assume it's because it's enclosed in an XPCNativeWrapper):
Error: Component returned failure code: 0x80040111 (NS_ERROR_NOT_AVAILABLE)
[nsIDOMCanvasRenderingContext2D.drawImage]
Putting GM_log() statements throughout my code, I have traced the image object I'm trying to use from it's initial assignment through until I try to use it with an HTML Canvas.
It's always wrapped in an XPCNativeWrapper:
[object XPCNativeWrapper [object HTMLImageElement]]
I've unwrapped the HTMLImageElement by obtaining reference to it with image.wrappedJSObject.
My canvas code:
var canvas = document.createElement("canvas");
canvas.width = image.width;
canvas.height = image.height;
var ctx = canvas.getContext("2d");
ctx.drawImage(image, 0, 0);
Any ideas why Firefox is throwing the above component failure code?
I should have looked more thoroughly on Google.
image.wrappedJSObject;
Works.
var canvas = document.createElement("canvas").wrappedJSObject,
ctx = canvas.getContext("2d");
canvas.width = image.width;
canvas.height = image.height;
ctx.drawImage(image, 0, 0);
this is what i did. hope it helps
I just had the same problem. The error went away when I used an absolute/complete URL for the image. Also, as someone else had noted, make sure the image is loaded first of all, or just create a new Image() in javascript first of all.
Working example for firefox 3.6.16 (I had similar problem):
http://userscripts.org/scripts/review/106800
Related
While drawing bitmap image onto off-screen canvas, Chrome console threw an error on me:
Failed to execute 'getContext' on 'OffscreenCanvas': The provided value 'bitmaprenderer' is not a valid enum value of type OffscreenRenderingContextType.
The problem occurs in both worker and window contexts:
var img = new Image(63, 177);
img.src = "https://cdn.sstatic.net/Img/unified/sprites.svg";
img.onload = _ => {
createImageBitmap(img).then(bitmap => {
var canvas = new OffscreenCanvas(bitmap.width, bitmap.height);
canvas.getContext('bitmaprenderer');
}).catch(e => console.error(e.message));
};
I can get this canvas context type in window context while using (on-screen) canvas interface as so:
document.createElement('canvas').getContext('bitmaprenderer');
The canvas context is needed in worker, so I can't use (on-screen) canvas interface, there is no document access after all.
While I can just get two-dimensional rendering context of bitmap image by using '2d' identifier in getContext method, it would be OffscreenCanvasRenderingContext2D and not ImageBitmapRenderingContext. I don't know the difference in latency for both interfaces, but as far as I understand, bitmap can be transferred onto canvas immediately, while 2d context should be drawn.
My Chrome version is 74.0.3729.169, and linked article browser compatibility table stipulates, that bitmap rendering context interface is available from 66 version.
Am I doing something wrong, or is bitmaprenderer not supported as a valid value for off-screen canvas rendering context as of now? How can I access bitmap rendering context for off-screen canvas in Chrome? Thanks in advance.
Yes, ImageBitmapRenderingContext is still not available from an OffscreenCanvas, only webgl[-2] (in FF and Chrome) and 2D (currently in Chrome only) are.
Note that it makes very little sense to make this ImageBitmapRenderingContext available from OffscreenCanvas since this context is generally only used to display ImageBitmap objects. This thus implies that the associated canvas should be visible.
If you wanted to use it for something like being able to draw it to a an other context, then you can directly pass the ImageBitmap to either 2D drawImage or webgl texImage2d.
So the only use case I can see for it would be to use the OffscreenCanvas.convertToBlob() method from inside a Worker in order to convert an ImageBitmap to a BLob. I can understand that devs did set it as low priority, when you can anyway already do the same by other means (even though it might use a bit more memory to achieve it).
Also note that in your case, since you are in the main thread and not in a Worker, you absolutely don't need an OffscreenCanvas and can just do
var img = new Image();
img.crossOrigin = 'anonymous';
img.src = "https://upload.wikimedia.org/wikipedia/commons/a/a4/Fiore_con_petali_arancioni_SVG.svg";
img.onload = _ => {
createImageBitmap(img)
.then(bitmap => {
const canvas = Object.assign(document.createElement('canvas'), {
width: bitmap.width,
height: bitmap.height
});
const ctx = canvas.getContext('bitmaprenderer');
ctx.transferFromImageBitmap(bitmap);
return new Promise((res, rej) => {
canvas.toBlob(blob => {
if (!blob) rej('error');
res(blob);
});
});
})
.then(blob => {
console.log(blob);
result.src = URL.createObjectURL(blob);
})
.catch(e => console.error(e.message));
};
PNG: <img id="result">
I'm trying to resize an image that uses a base64 encoded source. To do this I'm trying to use the canvas element's 2d draw image method for a canvas that is the side I'd like to scale down to.
This is what my method looks like:
resizeImage (base64Image) {
let vm = this
return new Promise((resolve, reject) => {
// let img = document.createElement('img') // I've tried both with the Image constructor and with the document createElement function
let img = new Image()
img.onload = () => {
let canvas = document.createElement('canvas')
let ctx = canvas.getContext('2d')
canvas.width = vm.resizeDimensions.width
canvas.height = vm.resizeDimensions.height
// at this point, the `this` context is referring to the img element we created
// this is also the point at which I hit the type error
ctx.drawImage(this, 0, 0, vm.resizeDimensions.width, vm.resizeDimensions.height)
let uri = canvas.toDataUrl()
resolve(uri)
}
img.src = base64Image
})
},
The thing that's throwing me for a loop is that when I step through the code in the debugger and do my own type check, the image created (regardless of construction method) is one of the valid types for the drawImage method:
sorry for the crossing arrows. I tried recording a gif but the file size was too large to upload to stackoverflow.
There's definitely something I'm missing here. Why is a type error being thrown even though I can confirm that the garget is indeed the correct type?
A bit more information: This is a electron/vue prototype for a larger project. The code with this bug is in a branch and subfolder of the project here if you want to dig in: https://github.com/chris-schmitz/matching-game/tree/image-encoding-prototype-errors/prototypes/saving-and-encoding-images.
Update
Here's a screenshot of the contents of this within the onload callback:
Also, the gif I recorded of the error happening can be found here:
I'm not sure what I'm doing wrong in this problem. I'm using OpenProcessing and trying to put a canvas element within a container but I'm running into an Uncaught TypeError, Cannot read property "id"
I'm copying the same code from https://github.com/processing/p5.js/wiki/Positioning-your-canvas
function setup() {
var cnv = createCanvas(100, 100);
var x = (windowWidth - width) / 2;
var y = (windowHeight - height) / 2;
cnv.position(x, y);
background(255, 0, 200);
}
This is my code...
function setup() {
var cnv = createCanvas(500, 100);
cnv.id("hello");
cnv.position(0,0);
}
function draw() {
}
Here is a link to my sketch...
https://www.openprocessing.org/sketch/407956
It has something to do with OpenProcessing because your code works absolutely fine on p5 editor (and locally).
The createCanvas method returns an object so calling the id function on it should not return "Cannot read property 'id' of undefined" as it did on OpenProcessing so createCanvas possibly isn't returning anything, and it should return an object according to p5 documentation..
You can try positioning the canvas using css as described in p5 wiki by adding a stylesheet that uses flexible box layout or try not using OpenProcessing if possible.
The createCanvas() function is not returning anything. This doesn't jive with what's in the P5.js reference, so I understand your confusion.
My guess is that OpenProcessing uses a slightly modified version of P5.js, because it doesn't really require any positioning. The canvas is always centered in the screen.
If you're going to continue using OpenProcessing, then I'd stop worrying about positioning the canvas yourself. Or I'd search for existing sketches that reposition the canvas and see how they do it.
Even if the createCanvas() function returns soemthing, I'm not sure what the id() function is supposed to do in this case. Nothing in the link you posted uses that function. Nonetheless, it seems to work fine if I run it locally.
I want to manipulate a canvas but I'm not able to call getContext on the canvas element which I get from Webdriver:
browser.findElement(webdriver.By.id('my-canvas')).then(function (canvas) {
var ctx = canvas.getContext('2d');
...
});
I've also tried canvas[0] but that doesn't work too, getContext is undefined. How can I reach this native canvas function ?
UPDATE: I've tried executeScript which works, but is extremely slow
Ok so I'm creating a game with JavaScript Canvas Elements and such. I've been able to load in TONS of Images, but on a select few, JavaScript replies with Errors such as
Uncaught TypeError: Failed to execute 'drawImage' on 'CanvasRenderingContext2D': No function was found that matched the signature provided.
Which makes NO SENSE at all, because the same code works in other places!?!
Here is an example I have in my code:
board.drawImage(document.getElementById("player_explode"), this.x, this.y);
Inside of an objects method, Player.die(), respectively.
Does anyone know why this behaviour is coming about? I'm getting very frustrated about it...
Here is a JSFiddle to demonstrate, alonside all the code.
Player.die() is located on line[242].
The problem was the way that I was loading my Images, I should've been doing:
var image = new Image();
image.src = "imagesource.jpg";
But instead I was get the elements by id from the document page.
Resources:
Explanation on loading images
Explanation on how html loads images
you should wait all elements load,so do like this:
window.onload=function(){
board.drawImage(document.getElementById("player_explode"), this.x, this.y);
}
For people in 2021 learning React, you have to call the context.drawImage() in the img.onload or nothing will be shown on the canvas! Here is a real world working example:
useEffect(() => {
canvasRef.current.width = mapXYWH.w * UNIT
canvasRef.current.height = mapXYWH.h * UNIT
const context = canvasRef.current.getContext("2d")
map.map(o => {
const img = new Image(o.width*UNIT,o.height*UNIT)
img.src = o.normal
img.onload = () =>
context.drawImage(img, (o.x-mapXYWH.x)*UNIT, (o.y-mapXYWH.y)*UNIT)
})
}, [map, mapXYWH])
See also: React -- Canvas Won't Draw Image