Why does canvas context drawImage fail on iPhone - javascript

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

Related

Adjusting the brightness of an image using canvas context in Microsoft Edge

I am building an application where I need to be able to capture a frame-grab from a web camera and upload it to the application. To do this, I am using WebRTC to capture the image from the video stream, write it to a canvas, and then grab the data and upload it. This works fine for the most part. However, I needed to give the user a way to adjust the brightness. To accomplish this, I added a slider to the page with the video stream on it, that applies "style.webkitFilter = 'brightness(X%)'" when adjusted. Again, this works fine, but did not adjust the brightness of the captured image, just the displayed video stream. The javascript function I use to actually capture the image is:
function takepicture() {
var context = canvas.getContext('2d');
var b = document.getElementById('txtBrightness').value;
if (width && height) {
canvas.width = width;
canvas.height = height;
context.filter = 'brightness(' + b + '%)';
context.drawImage(video, 0, 0, width, height);
var data = canvas.toDataURL();
//photo.setAttribute('src', data);
//alert(data);
document.getElementById('Image').value = data;
//$("#Image").val(data);
$("#form1").submit();
} else {
clearphoto();
}
}
This works in Chrome, Firefox, and the Chromium based version of Edge, however, it does NOT work in the EdgeHTML versions of Edge. In those versions of Edge, the video stream is correctly displayed with the adjusted brightness, but the captured image does not have the brightness adjusted. Is there a workaround to make context filters work with the EdgeHTML versions of the Edge browser?
From the CanvasRenderingContext2D.filter, it seems that CanvasRenderingContext2D.filter not support Microsoft Edge browser (EdgeHtml version).
As a workaround, you could try to use Konva plugin to apply filter to an image.
Sample code as below:
<head>
<meta charset="utf-8" />
<title></title>
<script src="https://unpkg.com/konva#4.1.3/konva.min.js"></script>
<meta charset="utf-8" />
<title>Konva Brighten Image Demo</title>
<style>
body {
margin: 0;
padding: 0;
overflow: hidden;
background-color: #f0f0f0;
}
#slider {
position: absolute;
top: 20px;
left: 20px;
}
</style>
</head>
<body>
<div id="container"></div>
<input id="slider" type="range" min="-1" max="1" step="0.05" value="0" />
<script>
function loadImages(sources, callback) {
var images = {};
var loadedImages = 0;
var numImages = 0;
for (var src in sources) {
numImages++;
}
for (var src in sources) {
images[src] = new Image();
images[src].onload = function () {
if (++loadedImages >= numImages) {
callback(images);
}
};
images[src].src = sources[src];
}
}
function buildStage(images) {
var stage = new Konva.Stage({
container: 'container',
width: window.innerWidth,
height: window.innerHeight
});
var layer = new Konva.Layer();
var lion = new Konva.Image({
image: images.lion,
x: 80,
y: 30,
draggable: true
});
lion.cache();
lion.filters([Konva.Filters.Brighten]);
layer.add(lion);
stage.add(layer);
var slider = document.getElementById('slider');
slider.oninput = function () {
lion.brightness(slider.value);
layer.batchDraw();
};
}
var sources = {
lion: '/images/lion.png'
};
loadImages(sources, buildStage);
</script>
</body>
The output like this:

HTML canvas element not displaying image

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();

Resize images with canvas before uploading

I have recently written a script to upload images. Everything works well. But now I want to resize the image after uploading it. I have done some research on it and I want to try it with the <canvas> element. I have parts of the script, others are missing and I don't know how to connect everything.
These are the steps:
Upload the image into img/uploads - Done.
<form action="picupload.php" method="post" enctype="multipart/form-data">
<input name="uploadfile" type="file" accept="image/jpeg, image/png">
<input type="submit" name="btn[upload]">
</form>
picupload.php:
$tmp_name = $_FILES['uploadfile']['tmp_name'];
$uploaded = is_uploaded_file($tmp_name);
$upload_dir = "img/uploads";
$savename = "[several code]";
if($uploaded == 1)
{
move_uploaded_file (
$_FILES['uploadfile']['tmp_name'] ,
"$upload_dir/$savename");
}
Put the image into a canvas element - Missing
Resize it - Part of the code I want to use somehow:
var MAX_WIDTH = 400;
var MAX_HEIGHT = 300;
var width = img.width;
var height = img.height;
if (width > height) {
if (width > MAX_WIDTH) {
height *= MAX_WIDTH / width;
width = MAX_WIDTH;
}
} else {
if (height > MAX_HEIGHT) {
width *= MAX_HEIGHT / height;
height = MAX_HEIGHT;
}
}
Replace the existing image with the new resized one. - Missing
It would be very nice if someone would give me some tips to complete it - Thank you!
(#2-3) Resizing the source image onto a canvas
Calculate the scaling factor required to fit MAX dimensions without overflow
Create a new canvas with the scaled dimensions
Scale the original image and draw it onto the canvas
Important! Be sure the source image is coming from the same domain as your web page or else toDataURL will fail for security reasons.
(#4) You can convert the canvas from #3 to an image with resizedImg.src=context.toDataURL
Example annotated code and a Demo:
var MAX_WIDTH = 400;
var MAX_HEIGHT = 300;
var img=new Image();
img.crossOrigin='anonymous';
img.onload=start;
img.src="https://dl.dropboxusercontent.com/u/139992952/multple/annotateMe.jpg";
function start(){
var canvas=fitImageOntoCanvas(img,MAX_WIDTH,MAX_HEIGHT);
// #4
// convert the canvas to an img
var imgResized=new Image();
imgResized.onload=function(){
// Use the new imgResized as you desire
// For this demo, just add resized img to page
document.body.appendChild(imgResized);
}
imgResized.src=canvas.toDataURL();
}
// #3
function fitImageOntoCanvas(img,MAX_WIDTH,MAX_HEIGHT){
// calculate the scaling factor to resize new image to
// fit MAX dimensions without overflow
var scalingFactor=Math.min((MAX_WIDTH/img.width),(MAX_HEIGHT/img.height))
// calc the resized img dimensions
var iw=img.width*scalingFactor;
var ih=img.height*scalingFactor;
// create a new canvas
var c=document.createElement('canvas');
var ctx=c.getContext('2d');
// resize the canvas to the new dimensions
c.width=iw;
c.height=ih;
// scale & draw the image onto the canvas
ctx.drawImage(img,0,0,iw,ih);
// return the new canvas with the resized image
return(c);
}
body{ background-color:white; }
img{border:1px solid red;}
I would recommend using ajax for upload, since when you upload you redirect to the php page.
But the example I didn't use it either
References:
http://stackoverflow.com/questions/12368910/html-display-image-after-selecting-filename
http://stackoverflow.com/questions/4459379/preview-an-image-before-it-is-uploaded
http://stackoverflow.com/questions/6011378/how-to-add-image-to-canvas
http://stackoverflow.com/questions/331052/how-to-resize-html-canvas-element
http://stackoverflow.com/questions/2142535/how-to-clear-the-canvas-for-redrawing
Here is what I have for html
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="utf-8">
<style>
</style>
<title>Something</title>
</head>
<body>
<form action="picupload.php" method="post" enctype="multipart/form-data">
<input name="uploadfile" type="file" accept="image/jpeg, image/png">
<input type="submit">
</form>
</body>
<script src="http://code.jquery.com/jquery-latest.min.js"
type="text/javascript"></script>
<script>
</script>
</html>
For PHP I used a different way for file upload (for instance I store the picture in localhost/):
<?php
if(isset($_FILES['uploadfile']['name'])){
$nameFile=$_FILES['uploadfile']['name'];
$pathFile = "C:/inetpub/wwwroot/" . $_FILES['uploadfile']['name'];
$file_tmp2=$_FILES['uploadfile']['tmp_name'];
move_uploaded_file($file_tmp2, $pathFile);
}
echo ("
<!DOCTYPE html>
<html>
<head>
<meta name='viewport' content='initial-scale=1.0, user-scalable=no'>
<meta charset='utf-8'>
<style>
</style>
<title>Something</title>
</head>
<body>
<canvas id='viewport' ></canvas>
<button onclick='change()'>change</button>
</body>
<script>
var canvas = document.getElementById('viewport'),
context = canvas.getContext('2d');
make_base();
function make_base()
{
base_image = new Image();
base_image.src = '").$_FILES['uploadfile']['name'];
echo("';
base_image.onload = function(){
context.drawImage(base_image, 100, 100);
}
}
function change(){
context.clearRect(0, 0, canvas.width, canvas.height);
context.drawImage(base_image, 0, 0, 400 ,300);
}
</script>")
?>

Moving image in a circular path purely using JavaScript

How can I make the imageObject to move in a circular path? Or more specific, what are the mathematical formulas needed to make it do so?
I am required to use setInterval with a function that caluclates the new coordinates of the picture. setInterval is supposed to call the function at least 20 times a second.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Graphics and animation using HTML5 Canvas</title>
<style>
#the-canvas { border: 1px dashed gray }
</style>
<script>
addEventListener('load', function() {
var x = document.getElementById("the-canvas");
var y = x.getContext("2d");
var imageObject = new Image();
imageObject.onload = function() {
y.drawImage(imageObject, 100, 200);
};
imageObject.src = "image.jpg";
});
</script>
</head>
<body>
<canvas id="the-canvas" width="500" height="400">
Your browser does not support the <canvas> element.
</canvas>
</body>
</html>
Mathematical formulas needed would be cosine in one dimension and sine in the other.
Something like this:
addEventListener('load', function() {
var x = document.getElementById("the-canvas");
var y = x.getContext("2d");
var imageObject = new Image();
var step = 0, radius = 50, speed = 0.05;
function spin() {
y.clearRect(0, 0, x.width, x.height);
y.drawImage(imageObject, 100 + radius * Math.cos(speed * step), 200 + radius * Math.sin(speed * step));
++step;
}
imageObject.onload = function() {
y.drawImage(imageObject, 100, 200);
setInterval(spin, 50); // 20 fps
};
imageObject.src = "image.jpg";
});

How to get the color of a pixel from image?

I want to get the color of a pixel from image with using pure JavaScript.
I wrote this script, but it did not work:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>Get Pixel</title>
<script type='text/javascript'>
window.onload = function() {
var canvas = document.createElement("canvas");
var pic = new Image();
pic.src = 'http://i.imgur.com/hvGAPwJ.png';
pic.onload = function() {
canvas.width = pic.width;
canvas.height = pic.height;
var ctx = canvas.getContext("2d");
ctx.drawImage(pic, 0, 0);}
var c = canvas.getContext('2d');
var p = c.getImageData(7, 7, 1, 1).data;
var hex = "RGB = " + p[0]+", "+p[1]+", "+p[2];
document.getElementById("output").innerHTML = hex;
}
</script>
</head>
<body>
<div id="output"></div>
</body>
</html>
How to change the code, what would he worked correctly?
For example for the picture "http://i.imgur.com/hvGAPwJ.png", the result should be RGB = 255, 255, 255.
Your code is almost (see below) correct in its self BUT unfortunately when you use images from other origins than the page itself certain criteria must be there for it to work due to CORS (security feature).
You cannot use images from other origins out of the box. The server they are on need to have accept-* header set to allow this.
If not your getImageData and toDataURL will be blank (throws a security error that you can see in the console).
If you don't have access to modify the server the only way to get around this is to use your own server as a image proxy (http://myServer/getImage.cgi|php|aspx...?http/otherServer/img)
As pointed on in comments always set src after onload so you are sure onload gets initialized.
var pic = new Image();
pic.onload = function() { /* funky stuff here */ };
pic.src = 'http://i.imgur.com/hvGAPwJ.png'; //Last
If you indent your script properly, the error becomes more apparent:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>Get Pixel</title>
<script type='text/javascript'>
window.onload = function() {
var canvas = document.createElement("canvas");
var pic = new Image();
pic.src = 'http://i.imgur.com/hvGAPwJ.png';
pic.onload = function() {
canvas.width = pic.width;
canvas.height = pic.height;
var ctx = canvas.getContext("2d");
ctx.drawImage(pic, 0, 0);
}
var c = canvas.getContext('2d');
var p = c.getImageData(7, 7, 1, 1).data;
var hex = "RGB = " + p[0]+", "+p[1]+", "+p[2];
document.getElementById("output").innerHTML = hex;
}
</script>
</head>
<body>
<div id="output"></div>
</body>
</html>
You are setting a function on the image's load event, but not waiting for it to happen before you update the contents of the div.
You should move everything inside the pic.onload function, apart from setting the pic.src:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>Get Pixel</title>
<script type='text/javascript'>
window.onload = function() {
var canvas = document.createElement("canvas");
var pic = new Image();
pic.onload = function() {
canvas.width = pic.width;
canvas.height = pic.height;
var ctx = canvas.getContext("2d");
ctx.drawImage(pic, 0, 0);
var c = canvas.getContext('2d');
var p = c.getImageData(7, 7, 1, 1).data;
var hex = "RGB = " + p[0]+", "+p[1]+", "+p[2];
document.getElementById("output").innerHTML = hex;
}
pic.src = 'http://i.imgur.com/hvGAPwJ.png';
}
</script>
</head>
<body>
<div id="output"></div>
</body>
</html>
Now the problem is just cross origin restrictions.
To solve cross origins restrictions, you may add this line:
pic.crossOrigin = "Anonymous";
Right after defining pic var.
May not work in some cases though.

Categories

Resources