Empty images when resizing images using canvas - javascript

I'm developing an image resizer for files from input field with multiple files.
The files are first added to an array of Json objects, because i use that array in my webapp to add, remove and rearrange objects.
My problem is that Firefox and IE11 both presents empty images when traversing trough the filelist, and I can't figure out what is going wrong, and i neither has figured out a workaround for Firefox and IE. Chrome resizes and show the images ok.
I have tried two diferent methods. A serial function traversing trough the files array, and a asyncronous read-resize-show function. Both have the same problem with empty images.
The HTML is:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1" />
<script src="test.js"></script>
</head>
<body>
<input type="file" name="file" id="file" onChange="showFile(this)" multiple>
<input type="button" value="Show one by one" onClick="showPicturesSerial(dataArray,0)">
<input type="button" value="Show asyncronous" onClick="showPicturesAsync(dataArray)">
<div id="imageListSer" style="width:auto;min-height:150px;border:1px solid black;"></div>
<div id="imageListAsn" style="width:auto;min-height:150px;border:1px solid black;"></div>
</body>
</html>
The JavaScript is:
dataArray=new Array();
showFile=function(obj){
for(i=0;i<obj.files.length;i++){
dataArray[i]={
file:obj.files[i],
data:{
name:obj.files[i].name,
size:obj.files[i].size,
type:obj.files[i].type
// Add more values
}
}
}
}
showPicturesSerial=function(files,i){
var imageListSer=document.querySelector("#imageListSer");
if(i==0)imageListSer.innerHTML="";
isPic=/^image\//
if(i<files.length&&isPic.test(files[i].file.type)){
var file=files[i].file;
var reader=new FileReader();
reader.onerror=function(error) {
console.log ("error",error);
i++;
setTimeout(showPicture(files,i),999999);
}
reader.onload=function(e) {
var canvas=document.createElement("canvas");
var tImg=document.createElement("img");
var src;
src=e.target.result;
tImg.src=src;
var MAX_WIDTH=150;
var MAX_HEIGHT=150;
var width=tImg.width;
var height=tImg.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;
}
}
canvas.width=width;
canvas.height=height;
var ctx=canvas.getContext("2d");
ctx.drawImage(tImg, 0, 0, width, height);
var img=document.createElement("img");
img.src=canvas.toDataURL();
var div=document.createElement("div");
div.style.display="inline-block";
div.appendChild(img)
div.appendChild(document.createElement("br"));
div.appendChild(document.createTextNode(file.name));
div.appendChild(document.createElement("br"));
div.appendChild(document.createTextNode(file.type));
imageListSer.appendChild(div);
console.log("finished:",file.name);
i++;
return showPicturesSerial(files,i);
}
reader.readAsDataURL(file);
}
}
function showPicturesAsync(files) {
var imageListAsn=document.querySelector("#imageListAsn")
for (var i=0; i < files.length; i++) {
if(i==0)imageListAsn.innerHTML="";
isPic=/^image\//
if(!isPic.test(files[i].file.type))return;
var file=files[i].file;
if (!/^image\//.test(file.type)) {continue;}
var canvas=document.createElement("canvas");
var img=document.createElement("img");
var div=document.createElement("div");
div.style.display="inline-block";
div.appendChild(img);
div.appendChild(document.createElement("br"));
div.appendChild(document.createTextNode(file.name));
div.appendChild(document.createElement("br"));
div.appendChild(document.createTextNode(file.type));
imageListAsn.appendChild(div);
var reader=new FileReader();
reader.onerror=function(error) {
console.log ("error",error);
}
reader.onload=(function(aImg) { return function(e) {
var bImg=document.createElement("img");
var canvas=document.createElement("canvas");
bImg.src=e.target.result;
var MAX_WIDTH=150;
var MAX_HEIGHT=150;
var width=bImg.width;
var height=bImg.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;
}
}
canvas.width=width;
canvas.height=height;
var ctx=canvas.getContext("2d");
ctx.drawImage(bImg, 0, 0, width, height);
aImg.src=canvas.toDataURL();
console.log("finished:",i);
};
})(img);
reader.readAsDataURL(file);
}
}
I hope someone can figure out this problem.

Related

Error displaying an image from localhost on p5js Canvas

Problem:
I am learning p5.js and I am following a tutorial from Coding Train YouTube channel. Everything was fine until I had to call a library function on an Image object. The problem is that I have instantiated the library in an object p and I'm using it's variables through p object. I don't know why it isn't recognizing the loadPixels() function. In the tutorial, the function works fine.
Error Message:
🌸 p5.js says: There's an error as "loadPixels" could not be called as a function
(on line 17 in help.html [file:///G:/Android/help.html:17:11]).
Verify whether "img" has "loadPixels" in it and check the spelling, letter-casing (Javacript is case-sensitive) and its type.
For more: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Not_a_function#What_went_wrong
Code:
<!DOCTYPE html>
<head>
<script src='p5/p5.js'></script>
</head>
<body>
<div id='container'></div>
<script>
let sketch = function(p) {
p.setup = function(){
p.createCanvas(56, 56);
img = new Image();
img.src = "scott.jpg";
}
p.draw = function() {
// p.drawingContext.drawImage(img, 0, 0);
p.loadPixels();
img.loadPixels();
for (var x=0; x<p.width; x++) {
for (var y=0; y<p.height; y++) {
// var d = p.dist(x, y, p.width/2, p.height/2);
var loc = x+y+p.width;
// p.pixels[loc] = p.color(d);
p.pixels[loc] = img.pixels[loc];
}
}
}
p.updatePixels();
};
new p5(sketch, 'container');
</script>
</body>
</html>
Edit:
As someone pointed out that the problem is that I'm using Image() which is the default Image class for javascript. I did some changes to my code but now it gives me this error.
Error :-
Uncaught DOMException: The operation is insecure. help.html:18
openWindow file:///G:/Android/help.html:18
onclick file:///G:/Android/help.html:1
Code :-
<!DOCTYPE html>
<head>
<script src='p5/p5.js'></script>
</head>
<body>
<button onclick="openWindow()">click me to open a new window.</button>
<div id='container'></div>
<script>
function openWindow() {
var newWindow = window.open("", "Import Image", "height=56,width=56,status=yes,toolbar=no,menubar=no,location=no");
newWindow.document.write("<canvas id='imagePlaceholder'>Canvas not supported!</canvas>");
var canvas = newWindow.document.getElementById("imagePlaceholder");
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0);
// console.log(ctx.getImageData(0, 0, 56, 56).data);
dest = ctx.getImageData(0, 0, 56, 56).data;
}
let sketch = function(p) {
p.setup = function(){
p.createCanvas(56, 56);
img = new Image();
img.src = "scott.jpg";
let dest = p.createImage(56, 56);
console.log(img);
}
p.draw = function() {
// p.drawingContext.drawImage(img, 0, 0);
// p.loadPixels();
img.loadPixels();
for (var x=0; x<p.width; x++) {
for (var y=0; y<p.height; y++) {
// var d = p.dist(x, y, p.width/2, p.height/2);
var loc = x+y+p.width;
// p.pixels[loc] = p.color(d);
p.pixels[loc] = img.pixels[loc];
}
}
}
p.updatePixels();
};
new p5(sketch, 'container');
</script>
</body>
</html>
Because you are specifically trying to load an image from a local computer as opposed to a publicly accessible URL, a file input with user interaction is going to be the only way to do this. This is a deliberate constraint put in place by web browsers to prevent a malicious webpage from illicitly reading data from your local files. However there is a much simpler way to get the image data from the file input onto your p5js canvas. In fact this exact use case can be seen in the documentation for the createFileInput function.
let input;
let img;
function setup() {
input = createFileInput(handleFile);
input.position(0, 0);
}
function draw() {
background(255);
if (img) {
image(img, 0, 0, width, height);
}
}
function handleFile(file) {
if (file.type === 'image') {
img = createImg(file.data, '');
img.hide();
} else {
img = null;
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.3.1/p5.min.js"></script>
</head>
<body>
</body>
</html>
One obvious problem here is that you are using the builtin Image() constructor, which creates an HTMLImageTag (see the MDN Article) instead of creating a p5js p5.Image object (see the p5js Reference). However there are several other issues. In p5js you need to load images in the preload function to ensure they are available when you start drawing (this is an asynchronous operation). You'd have a much easier time drawing images in p5js using the built in image function. If you are going to use pixel arrays, you need to understand the structure of these arrays. They don't store Color objects, they store 4 separate numbers for each color channel (red, green, blue, and alpha). So the indices in the array are not (x + y * width), but ((x + y * width) * 4 + channel) where channel is a number from 0 to 3. Also you need to account for the fact that the canvas may have a pixel density > 1, whereas the image will have a pixel density of 1. I strongly suggest you read all of the documentation for the Image related p5js functions.
let sketch = function(p) {
let img;
p.preload = function() {
img = p.loadImage("https://s3-ap-southeast-1.amazonaws.com/investingnote-production-webbucket/attachments/41645da792aef1c5054c33de240a52e2c32d205e.png");
};
p.setup = function() {
p.createCanvas(200, 200);
};
p.draw = function() {
// this would be a lot simpler way to draw the image:
// p.image(img, 0, 0);
p.loadPixels();
img.loadPixels();
// Handle high pixel density displays. This code effectively scale the image up so that each 1 pixel in the source image is density * density pixels in the display, thus preserving the size of the image but leading to visible pixelation.
let density = p.pixelDensity();
for (var x = 0; x < p.width && x < img.width; x++) {
for (var y = 0; y < p.height && y < img.height; y++) {
// There are 4 values per pixel in the pixels array:
var srcLoc = (x + y * img.width) * 4;
for (var xd = 0; xd < density; xd++) {
for (var yd = 0; yd < density; yd++) {
var destLoc =
(x * density + xd + (y * density + yd) * p.width * density) * 4;
for (var i = 0; i < 4; i++) {
p.pixels[destLoc + i] = img.pixels[srcLoc + i];
}
}
}
}
}
p.updatePixels();
};
};
new p5(sketch, 'container');
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.3.1/p5.min.js"></script>
</head>
<body>
<div id='container'></div>
</body>
</html>
Here is an alternate version of the snippet that handles pixelDensity differently:
let sketch = function(p) {
let img;
p.preload = function() {
img = p.loadImage("https://s3-ap-southeast-1.amazonaws.com/investingnote-production-webbucket/attachments/41645da792aef1c5054c33de240a52e2c32d205e.png");
};
p.setup = function() {
p.createCanvas(200, 200);
};
p.draw = function() {
// this would be a lot simpler way to draw the image:
// p.image(img, 0, 0);
p.loadPixels();
img.loadPixels();
// Handle high pixel density displays. This code shrinks the image down by mapping one pixel in the source image to 1 / (density ^ 2) actual pixels in the canvas.
let density = p.pixelDensity();
for (var x = 0; x < p.width * density && x < img.width; x++) {
for (var y = 0; y < p.height * density && y < img.height; y++) {
// There are 4 values per pixel in the pixels array:
var srcLoc = (x + y * img.width) * 4;
var destLoc = (x + y * p.width * density) * 4;
for (var i = 0; i < 4; i++) {
p.pixels[destLoc + i] = img.pixels[srcLoc + i];
}
}
}
p.updatePixels();
};
};
new p5(sketch, 'container');
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.3.1/p5.min.js"></script>
</head>
<body>
<div id='container'></div>
</body>
</html>
I tried a lot of things and almost giveup, but at the end I had to change the code a bit and this worked for me. Although what I got was base64 url as Alice in the comment suggested and I converted it into Uint8ClampedArray. Now if anyone wants a full image or all the pixels of an image then they can follow this link :- https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Pixel_manipulation_with_canvas . I hope it will be helpful for anyone who wants to make an offline webcanvas based application and don't want to dabble with CORS.
var fileSelector = document.createElement('input');
fileSelector.setAttribute('type', 'file');
fileSelector.setAttribute('accept', 'image/gif, image/jpeg, image/png');
fileSelector.click();
fileSelector.onchange = function(e) {
img = new Image();
var file = e.target.files[0];
var reader = new FileReader();
reader.onloadend = function() {
img.src = reader.result;
}
reader.readAsDataURL(file);
var newWindow = window.open("", "_blank", "height=56,width=56,status=yes,toolbar=no,menubar=no,location=no");
newWindow.document.write("<canvas id='imagePlaceholder'>Canvas not supported!</canvas>");
var canvas = newWindow.document.getElementById("imagePlaceholder");
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0);
// console.log(ctx.getImageData(0, 0, 56, 56).data);
var dest = ctx.getImageData(0, 0, img.width, img.height).data;
console.log(dest);
newWindow.close();
}

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>")
?>

problems with canvas

Here's my html document:
<html>
<head>
<meta charset="utf-8">
<title>Automapper Editor</title>
</head>
<body>
<nobr>
<script>
var img = new Image()
img.src = "grass_main_0.7.png"
for(var y=0; y < 16; y++) {
for(var x=0; x < 16; x++) {
var tilecanvas = document.createElement("canvas")
var tilectx = tilecanvas.getContext("2d")
tilecanvas.width = 64
tilecanvas.height = 64
tilecanvas.draggable = true
tilectx.drawImage(img, x*64, y*64, 64, 64, 0, 0, 64, 64)
document.body.appendChild(tilecanvas)
}
document.body.appendChild(document.createElement("br"))
}
</script>
</nobr>
</body>
</html>
I want to split an image with the size of 1024 pixel in 16 images with the size of 64 pixel. Then i want to draw them on canvas and write them to the document. This are my problems:
The line tilecanvas.draggable = true doesn't work, this should do the same as <canvas draggable="true">.
The <nobr> tag doesn't prevent the canvas from wrapping, but i want them to stay 16x16 on the screen.
The first time you load the page you can't see the image, you can simulate this by pressing STRG+F5 (a.k.a. Ctrl-F5) in firefox.
You can solve it by:
Using a container div for the tiles
Set fixed width for container element
Adjust the CSS for canvas element to float
Live example
(note: added random alpha for the tiles/demo to increase visibility)
var img = new Image();
img.onload = render;
img.src = "http://www.psdgraphics.com/file/colorful-triangles-background.jpg";
function render() {
var cont = document.getElementById("cont");
for (var y = 0; y < 16; y++) {
for (var x = 0; x < 16; x++) {
var tilecanvas = document.createElement("canvas");
var tilectx = tilecanvas.getContext("2d");
tilecanvas.width = 64;
tilecanvas.height = 64;
tilecanvas.draggable = true;
tilectx.globalAlpha = Math.random() + 0.5; // just to increase visuals
tilectx.drawImage(img, x * 64, y * 64, 64, 64, 0, 0, 64, 64);
cont.appendChild(tilecanvas);
}
}
}
#cont {width: 1024px;border: 1px solid #000}
canvas {float:left}
<div id="cont"></div>
As said by RienNeVaPlu͢s & Ken Fyrstenberg, make sure you give your image time to load with onload.
Here's a proof-of-concept allowing html drag-drop of a spliced image-canvases:
https://jsfiddle.net/m1erickson/g9nfuved/
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
<style>
body{ background-color: ivory; padding:10px; }
canvas{border:1px solid red; margin-left:0px;}
#dropzone{width:250px;height:50px;border:1px solid blue;}
</style>
<script>
$(function(){
var $results=$('#results');
var img=new Image();
img.onload=start;
img.src="https://dl.dropboxusercontent.com/u/139992952/stackoverflow/facesSmall.png";
function start(){
var w=img.width/4;
var h=img.height;
for(var x=0; x < 4; x++) {
var tilecanvas = document.createElement("canvas");
var tilectx = tilecanvas.getContext("2d");
tilecanvas.width = w;
tilecanvas.height = h;
tilecanvas.draggable = true
tilecanvas.id='canvas'+x;
tilectx.drawImage(img, x*w,0,w,h, 0, 0, w, h)
document.body.appendChild(tilecanvas)
tilecanvas.addEventListener('dragstart', function(e){
e.dataTransfer.setData('text',e.target.id);
}, false);
tilecanvas.addEventListener('dragenter', handleEvents, false);
tilecanvas.addEventListener('dragover', handleEvents, false);
tilecanvas.addEventListener('dragleave', handleEvents, false);
tilecanvas.addEventListener('dragend', handleEvents, false);
}
document.body.appendChild(document.createElement("br"))
var dropzone=document.getElementById('dropzone');
dropzone.addEventListener('dragover',function(e){e.preventDefault(); return(false);});
dropzone.addEventListener('dragenter',function(e){return(false);});
dropzone.addEventListener('drop',function(e){
$results.text('You dropped: '+e.dataTransfer.getData('text'));
return(false);
});
}
function handleEvents(e){ return(false); }
}); // end $(function(){});
</script>
</head>
<body>
<h4 id='results'>Drag 1+ of the image strips</h4>
<div id='dropzone' droppable='true'>Drop Here.</div>
</body>
</html>

Resize before upload with PHP & Javascript

Need a little help with resizing an image before uploading.
I'm using a brilliant solution that works perfectly when running it on a website but the second my mobile phone tries to upload from the gallery or camera is squashes the image quite badly.
HTML
<!DOCTYPE HTML>
<html>
<head>
<title>Upload Photos</title>
<link rel="stylesheet" href="./style.css" />
<head>
<body>
<h1>Upload Photos</h1>
<form enctype="multipart/form-data">
<input type="file" accept="image/*" />
<div class="photos">
</div>
</form>
<script src="./upload.js"></script>
</body>
</html>
Javascript
// Once files have been selected
document.querySelector('form input[type=file]').addEventListener('change', function(event){
// Read files
var files = event.target.files;
// Iterate through files
for (var i = 0; i < files.length; i++) {
// Ensure it's an image
if (files[i].type.match(/image.*/)) {
// Load image
var reader = new FileReader();
reader.onload = function (readerEvent) {
var image = new Image();
image.onload = function (imageEvent) {
// Add elemnt to page
var imageElement = document.createElement('div');
imageElement.classList.add('uploading');
imageElement.innerHTML = '<span class="progress"><span></span></span>';
var progressElement = imageElement.querySelector('span.progress span');
progressElement.style.width = 0;
document.querySelector('form div.photos').appendChild(imageElement);
// Resize image
var canvas = document.createElement('canvas'),
max_size = 1200,
width = image.width,
height = image.height;
if (width > height) {
if (width > max_size) {
height *= max_size / width;
width = max_size;
}
} else {
if (height > max_size) {
width *= max_size / height;
height = max_size;
}
}
canvas.width = width;
canvas.height = height;
canvas.getContext('2d').drawImage(image, 0, 0, width, height);
// Upload image
var xhr = new XMLHttpRequest();
if (xhr.upload) {
// Update progress
xhr.upload.addEventListener('progress', function(event) {
var percent = parseInt(event.loaded / event.total * 100);
progressElement.style.width = percent+'%';
}, false);
// File uploaded / failed
xhr.onreadystatechange = function(event) {
if (xhr.readyState == 4) {
if (xhr.status == 200) {
imageElement.classList.remove('uploading');
imageElement.classList.add('uploaded');
imageElement.style.backgroundImage = 'url('+xhr.responseText+')';
console.log('Image uploaded: '+xhr.responseText);
} else {
imageElement.parentNode.removeChild(imageElement);
}
}
}
// Start upload
xhr.open('post', 'process.php', true);
xhr.send(canvas.toDataURL('image/jpeg'));
}
}
image.src = readerEvent.target.result;
}
reader.readAsDataURL(files[i]);
}
}
// Clear files
event.target.value = '';
});
PHP
<?php
// Generate filename
$filename = md5(mt_rand()).'.jpg';
// Read RAW data
$data = file_get_contents('php://input');
// Read string as an image file
$image = file_get_contents('data://'.substr($data, 5));
// Save to disk
if ( ! file_put_contents('images/'.$filename, $image)) {
header('HTTP/1.1 503 Service Unavailable');
exit();
}
// Clean up memory
unset($data);
unset($image);
// Return file URL
echo './images/'.$filename;
?>
Any help to see why the images from a mobile phone is not working will be greatly appreciated.

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