HTML canvas element not displaying image - javascript

I was trying to use this tutorial to make a color picker. I am not very familiar with the canvas element, so I am just testing with the code from that link. I set the image src with a few different images, and none of them are appearing.
I'm not sure what i'd have to change to make it appear, but I tried changing the src, and that is not the problem. Basically when you click on the color wheel (the image on the canvas) an alert should pop up with the rgba value.
If I had to guess, maybe the problem is here? I would think you need an src before telling it what to do when it loads.
image.onload = () => canvasContext.drawImage(image, 0, 0, image.width, image.height);
image.src="https://i.stack.imgur.com/flqeC.jpg?s=256";
This is a jsfiddle with the code I have. I'm not the most experienced so this may be silly fix, but I appreciate any help!

In local its working fine here is full code
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style type="text/css">
body {
background-color: red;
}
#colorCanvas {
border: 1px solid #000000;
background-color:blue
}
</style>
</head>
<body>
<h1>Test</h1>
<canvas id="colorCanvas" class="color-canvas" width="250" height="250"></canvas>
</body>
<script type="text/javascript">
function initColorPicker() {
var canvasEl = document.getElementById('colorCanvas');
var canvasContext = canvasEl.getContext('2d');
var image = new Image(250, 250);
image.onload = () => canvasContext.drawImage(image, 0, 0, image.width, image.height);
image.src = "http://localhost/test/assets/img/color.jpg";
canvasEl.addEventListener('click', function (mouseEvent) {
{
var imgData = canvasContext.getImageData(mouseEvent.offsetX, mouseEvent.offsetY, 1, 1);
var rgba = imgData.data;
alert("rgba(" + rgba[0] + ", " + rgba[1] + ", " + rgba[2] + ", " + rgba[3] + ")");
}
})
}
initColorPicker();
</script>
</html>

Use Local Path of Image save that image in your local server otherwise you will get cross origin issue and then use this code
function initColorPicker()
{
var canvasEl = document.getElementById('colorCanvas');
var canvasContext = canvasEl.getContext('2d');
var image = new Image(250, 250);
image.onload = () => canvasContext.drawImage(image, 0, 0, image.width, image.height);
image.src="https://i.stack.imgur.com/flqeC.jpg?s=256";
canvasEl.addEventListener('click', function(mouseEvent) {
{
var imgData = canvasContext.getImageData(mouseEvent.offsetX, mouseEvent.offsetY, 1, 1);
var rgba = imgData.data;
alert("rgba(" + rgba[0] + ", " + rgba[1] + ", " + rgba[2] + ", " + rgba[3] + ")");
}
})
}
initColorPicker();

Related

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

Tainted canvas error thrown when refreshing the page with F5

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>

Canvas animation does not appear to be running at 60 fps

I'm trying to emulate how smooth this website is: http://material.cmiscm.com/ (You may have seen it before)
So, I'm starting very very small and simply trying to emulate the way the gradient in the purple section fades from the box. His gradient is diagonal -- for simplicity, mine is horizontal.
But, my problem is my gradient comes in very choppily, even when I try changing the value of RECT_INCREMENT
Fiddle: https://jsfiddle.net/16he6jfu/
Raw code (ctrl +v'able):
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<style>
#canvas {
padding: 0;
margin: 0;
}
body {
background: #6D00D0;
}
</style>
<body>
<canvas id="canvas" width="900" height="555">
</canvas>
</body>
<script>
var MAX_RECT_LENGTH = 800;
var RECT_INCREMENT = 50;
var RECT_X_ORIG = 0;
var RECT_Y_ORIG = 100;
var RECT_Y_MIN = 0;
var RECT_Y_MAX = 100;
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var gra = context.createLinearGradient(0, 0, 800, 0);
gra.addColorStop(0, 'rgba(229, 88, 95, .6)');
gra.addColorStop(1, 'rgba(255, 255, 255, 0)');
var path = 0;
function draw(){
if (path < MAX_RECT_LENGTH) {
context.beginPath();
// 1
context.moveTo(RECT_X_ORIG + path, RECT_Y_ORIG);
//console.log('1) ' + (RECT_X_ORIG + path) + ', ' + RECT_Y_ORIG);
// 2
path = path+RECT_INCREMENT;
context.lineTo(RECT_X_ORIG + path, RECT_Y_ORIG);
//console.log('2) ' + (RECT_X_ORIG + path) + ', ' + RECT_Y_ORIG);
// 3
context.lineTo(RECT_X_ORIG + path, RECT_Y_MIN);
//console.log('3) ' + (RECT_X_ORIG + path) + ', ' + RECT_Y_MIN);
// 4
context.lineTo(RECT_X_ORIG + path - RECT_INCREMENT, RECT_Y_MIN);
//console.log('4) ' + (RECT_X_ORIG + path - RECT_INCREMENT) + ', ' + RECT_Y_MIN);
// 5
context.lineTo(RECT_X_ORIG + path - RECT_INCREMENT, RECT_Y_MAX);
//console.log('5) ' + (RECT_X_ORIG + path - RECT_INCREMENT) + ', ' + RECT_Y_MAX);
context.closePath();
context.fillStyle=gra;
context.fill();
}
window.requestAnimationFrame(draw);
}
window.onload = function() {
window.requestAnimationFrame(draw);
}
</script>
</html>
Gradients are somewhat expensive to create. Instead of recreating a gradient on every animation loop, just create the full gradient rect at the start of your app and incrementally display it in the loop.
Here's example code and a Demo
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
var rect=createRectCanvas();
var width=1;
requestAnimationFrame(draw);
function draw(){
ctx.clearRect(0,0,cw,ch);
ctx.drawImage(rect,0,0,width,rect.height,0,0,width,rect.height);
width+=10;
if(width<cw && width<rect.width){
requestAnimationFrame(draw);
}
}
function createRectCanvas(){
var c=document.createElement('canvas');
var context=c.getContext('2d');
c.width=800;
c.height=100;
var gra = context.createLinearGradient(0, 0, 800, 0);
gra.addColorStop(0, 'rgba(229, 88, 95, .6)');
gra.addColorStop(1, 'rgba(255, 255, 255, 0)');
context.fillStyle=gra;
context.fillRect(0,0,800,100);
return(c);
}
body{ background-color: ivory; }
#canvas{border:1px solid red; margin:0 auto; }
<canvas id="canvas" width=900 height=500></canvas>

Javascript - drawImage can't reduce an image below certain resolution, regardless of canvas size

I'm having an issue with drawImage() re-sizing a loaded image below a certain width and height. The image I'm trying to re-size is 1080x1920 and I want it to be re-sized to 540x960. If I apply drawImage() to reduce it to 764x1358, it works. But any resolution smaller than that (on either parameter) results in the image not being displayed on the canvas.
There is definitely some correlation between the lower bounds on the resolution, because both are approximately 70.7% of the original resolution. I'm wondering if there's an inherit limit on drawImage but I couldn't find any specification that said so.
Here's the relevant code:
var image = new Image();
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
ctx.canvas.width = this.width * 2;
ctx.canvas.height = this.height;
$(image).on("load", function() {
ctx.drawImage(image, 0, 0, 764, 1358);
});
image.src = "test2.jpg";
I edited the code to show where image came from.
Full Code:
<!DOCTYPE html>
<html>
<head>
<title>Canvas from scratch</title>
<meta charset="utf-8">
<script
src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script src="jcanvas.min.js"></script>
</head>
<body>
<canvas id="myCanvas" width="1920" height="1920">
</canvas>
<script>
$(document).ready(
function() {
$("<img>").attr("src", "test2.jpg").on('load', function() {
var imgWidth, imgHeight;
var imageData;
var image = new Image();
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
ctx.canvas.width = this.width * 2;
ctx.canvas.height = this.height;
$(image).on("load", function() {
/* This is where the image is loaded and
inserted into the canvas */
ctx.drawImage(image, 0, 0, 763, 1358);
});
image.src = "test2.jpg";
imageData = ctx.getImageData(0, 0,
this.width,
this.height);
/* This is just part of the image manipulation,
bland right now */
var newImgData = ctx.createImageData(imageData.width,
imageData.height);
for ( var i = 0; i < newImgData.data.length; i += 4) {
newImgData.data[i + 0] = 255;
newImgData.data[i + 1] = 0;
newImgData.data[i + 2] = 0;
newImgData.data[i + 3] = 255;
}
// ctx.putImageData(newImgData, imageData.width, 0);
});
});
</script>
</body>
</html>
Last Edit: I found out the solution.
As it turns out, my issue was the version of JQuery I was using. I was originally just version 1, but 1.8.3 fixed everything. So, the solution is to simply change
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
to
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>

Why does canvas context drawImage fail on iPhone

The objective is to have the users choice of photograph displayed on both the image and canvas elements.
Why does this code work on Firefox, Chrome, IE, iPad but not on iPhone? On iPhone 3GS or iPhone 5 the canvas (red border) is simply shown blank albeit the correct size.
It does seem to work for iPhone screen captures but not photographs. Web Inspector gives us nothing.
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport"/>
<title></title>
<style type="text/css">
html, body{font-size:120%;}
#diag{ font-family:'Courier New';}
img{border:2px solid blue;}
canvas{border:2px solid red;}
</style>
<script type="text/javascript">
var reader = new FileReader();
var prev;
function go() {
prev = new Date();
diag('');
diag('start');
var imgFile = document.getElementById('submitfile');
if (imgFile.files && imgFile.files[0]) {
reader.onloadend = function () {
diag('reader.onloadend');
diag('reader.result.length=' + (reader.result.length / 1024.0 / 1024.0).toFixed(4) + "mb");
var img = new Image();
img.onload = function () {
diag('img.onload');
var cvs = document.createElement("canvas");
var ctx = cvs.getContext("2d");
diag("img.width:" + this.width);
diag("img.height:" + this.height);
cvs.width = this.width;
cvs.height = this.height;
diag("cvs.width:" + cvs.width);
diag("cvs.height:" + cvs.height);
ctx.drawImage(this, 0, 0);
ctx.font = '18pt Calibri';
ctx.fillStyle = 'red';
ctx.fillText('CANVAS COPY', 100, 100);
document.body.appendChild(cvs); // new canvas
document.body.appendChild(this); // img element
diag('ctx.drawImage');
};
img.src = reader.result;
}
}
reader.readAsDataURL(imgFile.files[0]);
diag('reader.readAsDataURL');
}
function diag(msg) {
var now = new Date();
var ms = now.getTime() - prev.getTime();
var current_diag_text = document.getElementById("diag").innerHTML;
var new_diag_text = ms + "ms " + msg + "<br/>" + current_diag_text;
if (msg === '') {
document.getElementById("diag").innerHTML = '';
} else {
document.getElementById("diag").innerHTML = new_diag_text;
}
prev = now;
}
</script>
</head>
<body>
<form name="Upload" action="#" enctype="multipart/form-data" method="post">
<p id="diag"></p>
<p>Choose Photo: <input type="file" name="submitfile" id = "submitfile" />
<input type="button" value="Send" onclick="go();" /></p>
</form>
</body>
</html>
We've now learnt of two issues here, one is a memory limitation of mobile safari described at https://developer.apple.com/library/safari/documentation/AppleApplications/Reference/SafariWebContent/CreatingContentforSafarioniPhone/CreatingContentforSafarioniPhone.html#//apple_ref/doc/uid/TP40006482-SW15. This can be overcome by adding portions of the image to canvas rather than all in one go. The next limitation is a problem with mobile safari scaling the resulting canvas image incorrectly.
Both of these issues are avoided by using the excellent mega pixel image rendering library # https://github.com/stomita/ios-imagefile-megapixel.
As to my knowledge above given Script is not even working on IPad

Categories

Resources