EaselJS : I'm trying to understand how Cross Domain works with bitmaps - javascript

I'm very new to javascript and EaselJS and I've searched the documentation as well as the questions here and I've learned that my initial problem with my mouse events not working with my bitmaps was because I'm trying to use bitmaps from a filepath on my computer.
I understand now that I need to use img.crossOrigin to allow easeljs to work with these images, but even though I'd added this, I still can't get this to work.
Here's what I have:
function init(){
var canvas = document.getElementById('game'); //assign canvas to variable
var stage = new createjs.Stage(canvas);
var term = new Image();
term.src = 'terminal.png';
term.crossOrigin = "Anonymous";
var oswin = new Image();
oswin.src = 'frame.png';
oswin.crossOrigin = "Anonymous";
var terminal = new createjs.Bitmap(term);
terminal.x = 28;
terminal.y = 36;
terminal.name = "terminal";
stage.addChild(terminal);
var oswindow = new createjs.Bitmap(oswin);
stage.addChild(oswindow);
oswindow.x = 196;
oswindow.y = 5;
oswindow.name = "oswindow";
//hide this bitmap
oswindow.visible = false;
//onclick to unhide the bitmap
terminal.on("click", handleClick);
stage.update();
}
function handleClick(){
oswindow.visible = true;
stage.update();
}
I've added in the crossOrigin and unfortunately, this still doesn't work and I've no idea why because I don't understand cross domain very well despite reading on it. (I'm a beginning programmer)
I work entirely offline right now, just trying to learn, so a way to fix this would be really nice.

Related

jspdf supplied data is not JPEG

I'm trying to get jspdf lib to show a jpeg image.
I do this:
src2 ="domain.com/images/pxPrescription/active_tick.jpg";
tickedImage = new Image();
tickedImage.src = src2;
src="domain.com/images/pxPrescription/no_tick.jpg";
no_tick = new Image();
no_tick.src = src;
doc.setFont('helvetica');
doc.setFontSize(10);
var basestarty = 190;
var basestartx = 15;
var offsetextra = 6;
var extraadd = 0.5;
var extratextoffsetx = basestartx + 10;
var extratextoffsety = basestarty + 10.5;
doc.text(extratextoffsetx, extratextoffsety, "Distance");
if(jQuery('#extraDist').is(":checked")){
doc.addImage(tickedImage, 'JPEG', basestartx, (basestarty+(offsetextra)+extraadd), 5, 5);
}else{
doc.addImage(no_tick, 'JPEG', basestartx, (basestarty+(offsetextra)+extraadd), 5, 5);
}
I also load the images into a hidden diff at page load to make sure they are available on the page.
I get Error: Supplied data is not a JPEG
Can someone help me solve this?
I'm not 100% sure since there isn't an environment to tinker with, but you should call
await no_tick.decode()
or
await tickedImage.decode()
as applicable in either of your if/else statements prior to adding the image to your pdf to ensure that you have valid image data available and then make your handler code an async function.
You're also welcome to use .then() as shown here:
https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/decode

PIXI js canvas pixels are saved as black for some reason

So I was trying to extract the pixels from my PIXI.js canvas, and I inspected them, and while the canvas on the screen had an image on it, the pixels extracted were completely black...
So then I investagated, and here is what I found (i need help)
Background info:
setup:
this.canvas = $('#canvas');
this.canvasDOM = this.canvas[0];
this.renderer = PIXI.autoDetectRenderer(0, 0, {
view: this.canvasDOM,
resolution: 1
});
Getting Image:
chooseImage(src) {
const self = this;
const image = new Image();
image.src = src;
image.onload = function() {
const base = new PIXI.BaseTexture(image);
const texture = new PIXI.Texture(base);
const sprite = new PIXI.Sprite(texture);
sprite.position.set(0, 0);
self.currentImage = sprite;
self.render();
};
}
rendering image:
render() {
if (this.currentImage) {
this.updateDimensions();
const stage = new PIXI.Container();
stage.addChild(this.currentImage);
stage.filters = this.gatherFilters();
const { width, height } = this.currentImage;
stage.filterArea = new PIXI.Rectangle(0, 0, width, height);
this.renderer.render(stage);
}
}
ok, so you can ignore the code which is before the rendering function, but in particular, the third last line of the rendering function is:
this.renderer.render(stage);
Now, this works perfectly fine! the image pops up and is a bright jellyfish on the canvas, but there is one small issue:
If i add this to the end of the render() function:
render() {
if (this.currentImage) {
this.updateDimensions();
const stage = new PIXI.Container();
stage.addChild(this.currentImage);
stage.filters = this.gatherFilters();
const { width, height } = this.currentImage;
stage.filterArea = new PIXI.Rectangle(0, 0, width, height);
this.renderer.render(stage);
const actualCanvas = this.renderer.extract.canvas; // the actual canvas on the screen
console.log(actualCanvas.toDataURL());
}
}
It returns a long string, and if replace
console.log(actualCanvas.toDataURL());
with: (the download lib)
download(actualCanvas.toDataURL('image/png'), 'image.png', 'image/png');
It downloads the jellyfish image!
now, in another function, I was going to have the image downloaded as either a png or jpg (and the array of possible download types was in another class and decided dynamically, so I couldn't simply cache the pixels after rendering)
to show u my issue, I will change the above code to:
setTimeout(() => download(actualCanvas.toDataURL('image/png'), 'image.png', 'image/png'), 1 /* One second delay */);
now the image is blank; black., unlike before when it worked
the only thing that changed was the delay I added.
I further inspected this, and i realised that if i did
setTimeout(() => console.log(this.renderer.extract.pixels()), 1); // extract the pixels after some delay for testing
then they were all black, but if i removed the delay, it worked again
again, in my case, I can't simply cache the image for my own reasons (don't ask)
So i was wandering if there was a workaround so that after some delay or later on the pixels when I extract them are not just black and work like it does without the delay.
Any help is greatly appreciated!
It seems some kind of browser protection to me. Maybe non-event-driven code protection accessing some resources or maybe non-https webapps protection (did you tried your app thru https even without certificate?), or maybe it can be even some kind of crossdomain protection (I doubt about it, but always present in the to-check list). Maybe you can deploy a fiddle or similar to test. Hope it helps!

How to synchronously draw an image to a canvas

I have an image encoded in base64 and I need to draw it on a canvas in a synchronous fashion. Take a look at this code I had:
//convert base64 to actual Image()
var input = new Image();
input.src = dataurl;
//draw on canvas
var w = input.width, h = input.height;
canvas.width = w; canvas.height = h;
ctx.drawImage(input, 0, 0)
This used to work on Chrome. I know it is not a good practice to assuming the browser will be able to finish loading before the next instruction, but it worked. After several updates later, it finally fails.
I cannot listen to the load event because that would make it async, which is not good because that's a generator function and I need to return the canvas synchronously. The program is built around it and making it async would mean complete rewrite. That's not good.
Attempt
input.src = dataurl;
while(!input.width){ /* busy wait */ }
var w = input.width, h = input.height;
Does not work since the browser won't update it before my code finishes executing.
Right now I really can't think of any way to solve this dilemma, so any input is appreciated. (Do note that the datauri is generated from another canvas, which I do have access to.)
It's not possible to draw an image to a canvas before it is loaded, which means waiting to a load event. This means you cannot load a data URI into an DOM image synchronously, so you will need to convert your API to an asynchronous one.
The only other way would be to have a JavaScript-based image decoder that converts the data URI into a ImageData object, which would not be trivial to do and require users to load a lot more code.
There used to be a different hack involving innerHTML that would work, but it too no longer works.
Now-Broken Example:
var base64 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJ4AAACeCAYAAADDhbN7AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyhpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMDE0IDc5LjE1Njc5NywgMjAxNC8wOC8yMC0wOTo1MzowMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6RkE1MTZBNzk1MDE1MTFFNUEzODE5OTE2QTE2M0ExOTYiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6RkE1MTZBNzg1MDE1MTFFNUEzODE5OTE2QTE2M0ExOTYiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTQgKE1hY2ludG9zaCkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpDM0YzRTJFODk1NDcxMUU0OUQ3NkI2RkYyOUFBMjg3RCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpDM0YzRTJFOTk1NDcxMUU0OUQ3NkI2RkYyOUFBMjg3RCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PgtvbosAAAnjSURBVHja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';
var el = document.createElement('p');
el.innerHTML = '<img src="'+base64+'" />';
var input = el.firstChild;
//draw on canvas
var canvas = document.getElementById('canvas');
var w = input.width, h = input.height;
canvas.width = w; canvas.height = h;
var ctx = canvas.getContext('2d');
ctx.drawImage(input, 0, 0);
<canvas id="canvas"></canvas>
Just use Promise to make it async.
return new Promise(resolve => {
image.onload = function () {
ctx.drawImage(input, 0, 0)
resolve('resolved');
}
});

Internet Explorer 9 sometimes draws blank images on canvas

I have a web application that generates images on the fly and then renders (segments of) them on the client using canvas - the general code looks something like this (simplified)...
var width = ...
var height = ...
var img = new Image();
img.onload = function(){ // Set onload before setting image source ;)
var canvas = document.createElement("canvas");
canvas.setAttribute('width',width);
canvas.setAttribute('height',height);
var context = canvas.getContext("2d");
context.drawImage(this,0,0,width,height,0,0,width,height);
}
img.src = ...
In firefox and chrome, this works fine. In IE9 (and sometimes IE10), this sometimes results in a blank image. As a workaround, I put in...
var width = ...
var height = ...
var img = new Image();
img.onload = function(){
var canvas = document.createElement("canvas");
canvas.setAttribute('width',width);
canvas.setAttribute('height',height);
var context = canvas.getContext("2d");
window.setTimeout(function(){
context.drawImage(img,0,0,width,height,0,0,width,height);
}, 10); // 10 millisecond delay here seems to give IE time to make sure the image is actually ready
}
img.src = ...
Obviously, putting in random delays is making me nervous - I would much rather figure out why this happens. Is there another event type / method / property on images that may be used? Could there perhaps be something in the http headers sent down with the images / the encoding / transfer method that is causing this?
Since drawing images on the canvas seems to be something that trips up new users a lot, searches mostly yield instances where the developer set the source before the onload method. The closest other question / reply I was able to find was this : https://stackoverflow.com/a/15186350/470062
Edit:
I have updated the examples to include width and height definitions at the start
Edit 29/Apr/2013:
The 10 millisecond delay is not always sufficient - I have changed the code to check the canvas pixels to determine if anything has been drawn - This feels like such an ugly hack though - I would love to know if there is a better way :
... snip - this is at the end of the image load callback..
if((navigator.appVersion.indexOf("MSIE")) >= 0){
function checkAndRedraw(){
context.clearRect(0,0,width,height);
context.drawImage(img, 0, 0, width, height);
var imageData = context.getImageData(0, 0, width, height),
data = imageData.data,
len = data.length;
for (var i = 0; i < len; i += 4){
if(data[i] || data[i+1] || data[i+2]){
scheduleRedraw = null; // prevent memory leak
return; // A pixel contained some non empty value so something was drawn - done.
}
}
scheduleRedraw();
}
var redrawHackTimeout;
function scheduleRedraw(){
window.clearTimeout(redrawHackTimeout);
redrawHackTimeout = window.setTimeout(checkAndRedraw, 500);
}
scheduleRedraw();
}
//END IE9 Hack
I have the same issue in IE9, what I had to do is this too:
theImage = new Image();
theImage.onload = function() {
that = this;
setTimeout(function() {
that.onload2();
}, 100);
};
theImage.onload2 = function(){
#your old load function code
}
theImage.src = 'http://....';
I don't understand why ie9 triggers load image function when it's not actually loaded or not "usable" yet in a canvas. it makes me pull my hair out.
var img = new Image();
img.src = ...
img.onload = function(){ // Set onload before after setting image source ;)
var canvas = document.createElement("canvas");
canvas.setAttribute('width',width);
canvas.setAttribute('height',height);
var context = canvas.getContext("2d");
context.drawImage(this,0,0,width,height,0,0,width,height);
}
You must set the src, then wait for the image to load.

drawImage using toDataURL of an html5 canvas

What I am doing now is the following:
I am storing the state of a canvas using the toDataURL method and I am also trying to draw it on a canvas using the drawImage method.
Here is a snippet:
var lastState = states[10]; //states is an array that saves all the toDataURL of the canvas
var permCtx = canvas.getContext('2d');
var img = new Image();
img.onload=function(){
permCtx.drawImage(img,0,0);
}
img.src=lastState;
I am getting the following error in the console:
414 (Request-URI Too Large)
Is there a way to draw an image on the canvas using only the toDataURL method?
The mechanism you have used should work; what OS/browser/version are you seeing this error with?
Anyhow, despite the fact that this should work, it is not the most efficient if you are constructing data URLs and then restoring them in the same session. Instead, I would suggest creating a new not-in-DOM canvas to store your state, and use that to draw to the main canvas:
var states = [];
function saveState(ctx){
var c = document.createElement('canvas');
c.width = ctx.canvas.width;
c.height = ctx.canvas.height;
c.getContext('2d').drawImage(ctx.canvas,0,0);
states.push(c);
return c;
}
function restoreState(ctx,idx){
var off = idx==null ? states.pop() : states[idx];
ctx.drawImage(off,0,0);
}

Categories