Tainted canvas error thrown when refreshing the page with F5 - javascript

I have problem with my code, which is quite similar to this CodePen.
var img = new Image();
img.src = 'https://upload.wikimedia.org/wikipedia/commons/thumb/6/63/Diceros_bicornis.jpg/320px-Diceros_bicornis.jpg';
img.crossOrigin = "Anonymous"
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
img.onload = function() {
ctx.drawImage(img, 0, 0);
img.style.display = 'none';
};
var color = document.getElementById('color');
function pick(event) {
var x = event.layerX;
var y = event.layerY;
var pixel = ctx.getImageData(x, y, 1, 1);
var data = pixel.data;
var rgba = 'rgba(' + data[0] + ', ' + data[1] +
', ' + data[2] + ', ' + (data[3] / 255) + ')';
color.style.background = rgba;
color.textContent = rgba;
}
canvas.addEventListener('mousemove', pick);
<!-- Learn about this code on MDN: https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Pixel_manipulation_with_canvas -->
<canvas id="canvas" width="300" height="227" style="float:left"></canvas>
<div id="color" style="width:200px;height:50px;float:left"></div>
It somehow certainly works when the page is first open. But when I refresh the page with F5, it SOMETIMES starts throwing the tainted canvas error. Only when I click x to close the tab, and then click the link again to open a brand new tab will it certainly work again.
I already have img.crossOrigin = "Anonymous".

That sounds like a chrome bug, but easily workaround-able :
Set your crossOrigin attribute first.
The first time the request is made, the crossOrigin attribute is set before the image has loaded, hence your browser will redo the request.
But when you reload the page, the image is already cached, and loads before the crossOrigin attribute is set. Then your canvas will be tainted.
For similar little bugs cases, you should also define your onload event handler before setting this src attribute :
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var img = new Image();
img.crossOrigin = "Anonymous"
img.onload = function() {
ctx.drawImage(img, 0, 0);
img.style.display = 'none';
};
// set the src last
img.src = 'https://upload.wikimedia.org/wikipedia/commons/thumb/6/63/Diceros_bicornis.jpg/320px-Diceros_bicornis.jpg';
var color = document.getElementById('color');
function pick(event) {
var x = event.layerX;
var y = event.layerY;
var pixel = ctx.getImageData(x, y, 1, 1);
var data = pixel.data;
var rgba = 'rgba(' + data[0] + ', ' + data[1] +
', ' + data[2] + ', ' + (data[3] / 255) + ')';
color.style.background = rgba;
color.textContent = rgba;
}
canvas.addEventListener('mousemove', pick);
<!-- Learn about this code on MDN: https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Pixel_manipulation_with_canvas -->
<canvas id="canvas" width="300" height="227" style="float:left"></canvas>
<div id="color" style="width:200px;height:50px;float:left"></div>

Related

How do I make the canvas display the recoloured image instead of the same image?

I had an image of Canada and manually recolored its pixels to shades of blue. I then tried to make a script that would do the same(into red) without me going through all the hassle.
But for some reason, the canvas simply repaints the same image of the blue Canada in Mozilla and Chrome(sometimes not even draws it).
Mozilla says accessing ImageData is a security error. What did I get wrong and how do I fix it?
Snippet right here:
canvas = document.getElementById("canvas");
context = canvas.getContext("2d");
var imgPath = "https://upload.wikimedia.org/wikipedia/commons/thumb/d/d8/Copper_sulfate.jpg/234px-Copper_sulfate.jpg";
var imgObj = new Image();
imgObj.crossOrigin = "anonymous";
imgObj.src = imgPath;
imgObj.onload = function() {
context.drawImage(imgObj, 0, 0);
map = context.getImageData(0, 0, 234, 240);
imagedata = map.data;
for (p = 0; p < imagedata.length; p += 4) {
imagedata[p] = imagedata[p + 2];
imagedata[p + 2] = 0;
imagedata[p + 3] = 255;
};
context.putImageData(map, 0, 0);
};
<img id="Canada" src="https://upload.wikimedia.org/wikipedia/commons/thumb/d/d8/Copper_sulfate.jpg/234px-Copper_sulfate.jpg" />
<canvas id='canvas' width='234px' height='240px'></canvas>

How to load dynamically created img element with jquery into HTML5 canvas

I cannot load/ display image created with jquery on HTML5 canvas but it works when image object is created as = new Image();
In particular, using this script as example: https://www.html5canvastutorials.com/advanced/html5-canvas-invert-image-colors-tutorial/
but substituting img source with:
imageObj.src = 'https://demo.boundlessgeo.com/geoserver/ows?&service=WMS&request=GetMap&layers=nasa%3Abluemarble&styles=&format=image%2Fjpeg&transparent=false&version=1.1.1&width=256&height=256&srs=EPSG%3A3857&bbox=0,2504688.542848655,2504688.5428486555,5009377.085697314';
and adding attribute: imageObj.crossOrigin = "Anonymous";
just after: var imageObj = new Image();
it allows for editing function to run and the image draws on canvas.
However, by creating the image with the following jquery, the image is not displayed in canvas and no errors are reported in the console:
var imageObj = $("<img />",
{
crossOrigin: "Anonymous",
src: "https://demo.boundlessgeo.com/geoserver/ows?&service=WMS&request=GetMap&layers=nasa%3Abluemarble&styles=&format=image%2Fjpeg&transparent=false&version=1.1.1&width=256&height=256&srs=EPSG%3A3857&bbox=0,2504688.542848655,2504688.5428486555,5009377.085697314"
});
Am I missing a step that binds img to document or is it something else?
In order to change the image creation in the example code you forgot the load event. Hence, your code should be:
var imageObj = $("<img />", {
crossOrigin: "Anonymous",
src: "https://demo.boundlessgeo.com/geoserver/ows?&service=WMS&request=GetMap&layers=nasa%3Abluemarble&styles=&format=image%2Fjpeg&transparent=false&version=1.1.1&width=256&height=256&srs=EPSG%3A3857&bbox=0,2504688.542848655,2504688.5428486555,5009377.085697314"
}).on('load', function (e) {
drawImage(this);
});
var imageObj = $("<img />", {
crossOrigin: "Anonymous",
src: "https://demo.boundlessgeo.com/geoserver/ows?&service=WMS&request=GetMap&layers=nasa%3Abluemarble&styles=&format=image%2Fjpeg&transparent=false&version=1.1.1&width=256&height=256&srs=EPSG%3A3857&bbox=0,2504688.542848655,2504688.5428486555,5009377.085697314"
}).on('load', function (e) {
drawImage(this);
});
function drawImage(imageObj) {
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var x = 69;
var y = 50;
context.drawImage(imageObj, x, y);
var imageData = context.getImageData(x, y, imageObj.width, imageObj.height);
var data = imageData.data;
for (var i = 0; i < data.length; i += 4) {
// red
data[i] = 255 - data[i];
// green
data[i + 1] = 255 - data[i + 1];
// blue
data[i + 2] = 255 - data[i + 2];
}
// overwrite original image
context.putImageData(imageData, x, y);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas id="myCanvas" width="578" height="400"></canvas>

Compare two images color values parallel with canvas

I am trying to create a JS-Application which allows to compare image values from two images at the same position.
My idea is to upload the images and store them as variables in an object. If I move my mouse a canvas element in the browser, the coordinates should be taken from this and be used to request the image-values from the stored canvases.
const images = new ImageHandler(); // ToDo: UpperCaseLetters as constant
(function createFileUploadButton() {
var x = document.createElement("INPUT");
x.setAttribute("type", "file");
x.id = "imageUploader";
document.body.appendChild(x);
})();
function ImageHandler() {
const WIDTH = 1030;
const HEIGHT = 650;
let upperImage = null;
let lowerImage = null;
this.setImage = imageData => {
if (upperImage && lowerImage) {
alert("Seite neu laden, um neue Bilder zu laden");
}
console.log("lowerImage: " + lowerImage)
if (!lowerImage) {
let canvas = this.getNewCanvasWithImage(imageData);
console.log("setting lower image")
lowerImage = canvas;
} else {
console.log("ELSE");
let canvas = this.getNewCanvasWithImage(imageData);
console.log("setting upper image")
upperImage = canvas;
}
};
this.getNewCanvasWithImage = imageData => {
console.log("getNewCanvas")
console.log("typeof imageData " + typeof imageData);
let canvas = document.createElement('canvas');
//canvas.id = "";
//canvas.style.zIndex = 2; ? Wofür gut? Brauchen wir das?
canvas.width = WIDTH;
canvas.height = HEIGHT;
let context = canvas.getContext('2d');
let image = new Image();
image.src = imageData;
context.drawImage(image, 1, 1);
return canvas;
};
this.getColorValues = (coordinates) => {
console.log("X " + coordinates.x);
console.log("Y " + coordinates.y);
var lowerImageContext = lowerImage.getContext('2d');
var lowerImageData = lowerImageContext.getImageData(coordinates.x, coordinates.y, 1, 1).data;
console.log("lowerImageData: " + lowerImageData);
var upperImageContext = upperImage.getContext('2d');
var upperImageData = upperImageContext.getImageData(coordinates.x, coordinates.y, 1, 1).data;
console.log("upperImageData: " + upperImageData);
};
this.drawUpper = () => {
console.log("appendUpper to body");
};
this.drawLower = () => {
document.appendChild(this.lowerImage);
};
}
document.getElementById("imageUploader").onchange = function(event) {
var input = event.target;
var reader = new FileReader();
// Callback when the file is loaded
reader.onload = function() {
try {
var filecontent = reader.result; // Loaded content
images.setImage(filecontent);
} catch (error) {
alert(error);
}
};
// Read the file
reader.readAsDataURL(input.files[0]);
};
$('#canvas').mousemove(function(e) {
console.log("mousemove");
var pos = findPos(this);
var xPos = e.pageX - pos.x;
var yPos = e.pageY - pos.y;
//var coordinates = "x=" + x + ", y=" + y;
console.log("x=" + xPos + ", y=" + yPos);
var coordinates = {};
coordinates.x = xPos;
coordinates.y = yPos;
images.getColorValues(coordinates);
});
function findPos(obj) {
var curleft = 0, curtop = 0;
if (obj.offsetParent) {
do {
curleft += obj.offsetLeft;
curtop += obj.offsetTop;
} while (obj = obj.offsetParent);
return {x: curleft, y: curtop};
}
return undefined;
}
<!DOCTYPE html>
<html>
<head>
<title>TODO supply a title</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<div>
<canvas id="canvas" width="300" height="250" style="border:1px solid #000000;"></canvas>
</div>
</body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.0/jquery.min.js"></script>
</html>
Unfortunately I can not find my error.
I get for the image values only zeros.
One aspect could be that the images need time to load but even if i wait several moments it does not work properly. Sometimes I get the values from one image but never from both.
Can anyone spot the error or has an idea how one could compare the color values from two images more easily?
Kind regards
Niklas
Using onload event of Image can help you make sure that the image is loaded and ready for use.
let image = new Image();
image.onload = function(){
context.drawImage(this, 1, 1);
}
image.src = imageData;
That being said, I am not sure if there are other issues in your code.
If you try to call drawImage() before the image has finished loading,
it won't do anything (or, in older browsers, may even throw an
exception). So you need to be sure to use the load event so you don't
try this before the image has loaded:
You can check this page for a comprehensive documentation

Drawing image in canvas in iframe

I have a canvas element in HTML file which i am calling in an <iframe>. The problem is canvas loads some images while ignores others. Even some time the same image doesn't get drawn. I have tried multiple solutions. Path is of local filesystem. The image gets downloaded to the server first and then the script is called. Following is my JS script:
function loadCanvas(e) {
alert(e.getSource().getProperty("sourcePath"));
var path = e.getSource().getProperty("sourcePath");
var source = e.getSource();
alert('source' + source);
var ADFiframe = source.findComponent("if1");
alert('ADFiframe' + ADFiframe);
var iframe = document.getElementById(ADFiframe.getClientId()).firstChild;
alert('iframe' + iframe);
var innerDoc = (iframe.contentDocument) ? iframe.contentDocument : iframe.contentWindow.document;
alert('innerDoc' + innerDoc);
var canvas = innerDoc.getElementById("imageView");
alert('canvas' + canvas);
var context = canvas.getContext('2d');
var img = new Image();
img.src = path;
alert('path' +path);
img.onload = function() {
alert('img.src' + img.src);
alert('Press OK to load your image');
context.drawImage(img, 0, 0, 700, 700);
};
// img.onerror= function(){
// alert('Ooops,Error loading this image');
// };
}

Generating a thumbnail for HTML5 CORS <video>

This question has 2 parts, really - the getting of the thumbnail image using canvas is straight forward. K Scott Allen did a post of this here
Basically, this is the code and I have tried it:
$output = $("#output");
var video = $("#video").get(0);
var canvas = document.createElement("canvas");
canvas.width = $video.videoWidth * scale;
canvas.height = $video.videoHeight * scale;
canvas.getContext('2d')
.drawImage($video, 0, 0, canvas.width, canvas.height);
var img = document.createElement("img");
img.src = canvas.toDataURL();
$output.prepend(img);
The second part is more complicated. Since my .mpg videos are being served by Azure Media Services, the call to canvas.getDataUrl() is a Cross Domain request and fails.
Setting CORS headers/flags should work but does not. There is a work around for images contained in the answer to this StackOverflow question here.
This work around has the following code example function that runs on body load:
function initialize() {
//will fail here if no canvas support
try {
var can = document.getElementById('mycanvas');
var ctx = can.getContext('2d');
var img = new Image();
img.crossOrigin = '';
//domain needs to be different from html page domain to test cross origin security
img.src = 'http://lobbydata.com/Content/images/bg_price2.gif';
} catch (ex) {
document.getElementById("results").innerHTML = "<span style='color:Red;'>Failed: " + ex.Message + "</span>";
}
//will fail here if security error
img.onload = function () {
try {
var start = new Date().getTime();
can.width = img.width;
can.height = img.height;
ctx.drawImage(img, 0, 0, img.width, img.height);
var url = can.toDataURL(); // if read succeeds, canvas isn't dirty.
//get pixels
var imgd = ctx.getImageData(0, 0, img.width, img.width);
var pix = imgd.data;
var len = pix.length;
var argb = []; //pixels as int
for (var i = 0; i < len; i += 4) {
argb.push((pix[i + 3] << 24) + (pix[i] << 16) + (pix[i + 1] << 8) + pix[i + 2]);
}
var end = new Date().getTime();
var time = end - start;
document.getElementById("results").innerHTML = "<span style='color:Green;'>" +
"Success: Your browser supports CORS for cross domain images in Canvas <br>"+
"Read " + argb.length+ " pixels in "+ time+"ms</span>";
} catch (ex) {
document.getElementById("results").innerHTML = "<span style='color:Red;'>Failed: " + ex + "</span>";
}
}
}
So my question is how do I modify K. Scott Allens' code to correctly set the CORS headers and generate the thumbnail from the video rather than the img as its in the example?
I have tried by setting crossOrigin ="" and crossOrigin="Anonymous" on both the video element and the canvas with no luck.
Any help would be appreciated.
Roberto
PS. There is a test for browser CORS image support here. And thsi method of getting the thumbnail does work. There's a page that uses it here (tho, no cross domain stuff)

Categories

Resources