drawImage doesnt work in canvas - javascript

I would like to use canvas to compress image file uploaded by user.
my js code is here.
function canvasDraw() {
var file = $("#imageSelect").prop("files")[0];
if (file["type"] != "image/jpeg" && file["type"] != "image/png" && file["type"] != "image/gif") {
$("#imageSelect").val('');
} else {
var fr = new FileReader();
fr.onload = function() {
$("#preview").attr('src', fr.result);
var image = new Image(); 
image.src = $("#preview").attr('src');
var w = 800;
var ratio = w / image.width;
var h = image.height * ratio;
var canvas = $("#canvas");
var ctx = canvas[0].getContext('2d');
$("#canvas").attr("width", w);
$("#canvas").attr("height", h);
ctx.drawImage(image, 0, 0, w, h);
};
fr.readAsDataURL(file);
}
}
<input type="file" name="picture" class='picture' accept="image/*" size="30" id="imageSelect" onChange="canvasDraw();" >
<img src="" id="preview" />
<canvas id="canvas"></canvas>
But in canvas, there is no image shown.
image.width and image.height doesnt work. And ctx.drawImage(image, 0, 0, w, h) doesnt work.
Could you tell me why I have this problem?

image.onload you need to load the image in onload event handler. After load complete it will draw in canvas.
function canvasDraw() {
var file = $("#imageSelect").prop("files")[0];
//画像ファイルかチェック
if (file["type"] != "image/jpeg" && file["type"] != "image/png" && file["type"] != "image/gif") {
alert("画像ファイルを選択してください");
$("#imageSelect").val(''); //選択したファイルをクリア
} else {
var fr = new FileReader();
fr.onload = function() {
//選択した画像を一旦imgタグに表示
$("#preview").attr('src', fr.result);
//imgタグに表示した画像をimageオブジェクトとして取得
var image = new Image(); 
image.src = $("#preview").attr('src');
image.onload = function() {
//縦横比を維持した縮小サイズを取得
var w = 800;
var ratio = w / image.width;
var h = image.height * ratio;
//canvasに描画
var canvas = $("#canvas");
var ctx = canvas[0].getContext('2d');
$("#canvas").attr("width", w);
$("#canvas").attr("height", h);
ctx.drawImage(image, 0, 0, w, h);
}
};
fr.readAsDataURL(file);
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="file" name="picture" class='picture' accept="image/*" size="30" id="imageSelect" onChange="canvasDraw();" >
<img src="" id="preview" />
<canvas id="canvas"></canvas>

Related

How to input an image and use that as the cursor?

I am trying to make a cursor changer, where the user can upload an image, and it will be the cursor anywhere on the document <body>. However it doesn't seem to work. I have tried .append and .appendChild, but it doesn't seem to work. Where have I gone wrong?
function readURL(input) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function(e) {
$('#uploaded1').attr('src', e.target.result);
$("#upload-cursor").css("display", "block");
$("#upload-cursor").click(function() {
$("body").css("cursor", "url(" + e.target.result + "), auto");
});
};
reader.readAsDataURL(input.files[0]);
}
}
$("#imgInp").change(function() {
readURL(this);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h5>Upload Cursor</h5>
<form runat="server">
<input type='file' id="imgInp">
<img id="uploaded1" src="#" width="50px" height="50px">
<br>
</form>
<button id="upload-cursor" style="display: none;">Create Cursor</button>
As the above answer, you image size might be big so do resize the Image.
to resize use the File API, then you can process the images with the canvas element.
This Mozilla Hacks blog post walks you through most of the process. For reference here's the assembled source code from the blog post:
// from an input element
var filesToUpload = input.files;
var file = filesToUpload[0];
var img = document.createElement("img");
var reader = new FileReader();
reader.onload = function(e) {img.src = e.target.result}
reader.readAsDataURL(file);
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0);
var MAX_WIDTH = 800;
var MAX_HEIGHT = 600;
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;
}
}
canvas.width = width;
canvas.height = height;
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0, width, height);
var dataurl = canvas.toDataURL("image/png");
//Post dataurl to the server with AJAX
Resizing before uploading:
HTML5 Pre-resize images before uploading

how to get entire image inside a canvas element?

I have a canvas element and want to load an entire image inside.
The canvas should be max 50% width.
The loaded images have different widths and heights but in any case I need entire image inside and not just a part of them.
Is it possible?
var URL = window.webkitURL || window.URL;
window.onload = function() {
var input = document.getElementById('input');
input.addEventListener('change', handleFiles, false);
}
function handleFiles(e) {
var ctx = document.getElementById('canvas').getContext('2d');
var url = URL.createObjectURL(e.target.files[0]);
var img = new Image();
img.onload = function() {
ctx.drawImage(img, 10, 10);
}
img.src = url;
}
#canvas{
max-width:50%;
}
<input type="file" id="input"/>
<canvas id="canvas"/>
drawImage's 4th and 5th parameter is the width and height. The example below will occupy the whole canvas.
var URL = window.webkitURL || window.URL;
window.onload = function() {
var input = document.getElementById('input');
input.addEventListener('change', handleFiles, false);
}
function handleFiles(e) {
var ctx = document.getElementById('canvas').getContext('2d');
var url = URL.createObjectURL(e.target.files[0]);
var img = new Image();
img.onload = function() {
ctx.drawImage(img, 0, 0, ctx.canvas.width, ctx.canvas.height);
}
img.src = url;
}
#canvas {
background-color: salmon;
max-width: 50%;
}
<input type="file" id="input" />
<canvas id="canvas" />
If you want a proportional image, we can use the solution here in calculating
var URL = window.webkitURL || window.URL;
window.onload = function() {
var input = document.getElementById('input');
input.addEventListener('change', handleFiles, false);
}
function handleFiles(e) {
var ctx = document.getElementById('canvas').getContext('2d');
var url = URL.createObjectURL(e.target.files[0]);
var img = new Image();
img.onload = function() {
var newDimen = calculateAspectRatioFit(img.width, img.height, ctx.canvas.width, ctx.canvas.height);
ctx.drawImage(img, 0, 0, newDimen.width, newDimen.height);
}
img.src = url;
}
function calculateAspectRatioFit(srcWidth, srcHeight, maxWidth, maxHeight) {
var ratio = Math.min(maxWidth / srcWidth, maxHeight / srcHeight);
return {
width: srcWidth * ratio,
height: srcHeight * ratio
};
}
#canvas {
background-color: salmon;
max-width: 50%;
}
<input type="file" id="input" />
<canvas id="canvas" />
If you want a centralized image, you can:
function handleFiles(e) {
var ctx = document.getElementById('canvas').getContext('2d');
var url = URL.createObjectURL(e.target.files[0]);
var img = new Image();
img.onload = function() {
var newDimen = calculateAspectRatioFit( img.width, img.height, ctx.canvas.width, ctx.canvas.height );
var tSpace = ( ctx.canvas.height - newDimen.height ) / 2;
var lSpace = ( ctx.canvas.width - newDimen.width ) / 2;
ctx.drawImage(img, lSpace, tSpace, newDimen.width, newDimen.height);
}
img.src = url;
}

JQuery client side resize with loading error / getting height width of image

this is my first post, so, please, be nice
removing these lines.
<!--This 1x1 picture size workaround is a real flower-->
<img src="" id="preview" width="1" height="1">
causes the below script to malfunction. Can someone explain what I'm doing wrong?
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script>
$(document).ready(function() {
$('#imageFile').change(function(evt) {
var files = evt.target.files;
var file = files[0];
//reader.onprogess = function(event) {
// document.getElementById('progressbar').innerHTML = "Progressbar";
// sleep
// };
if (file) {
var reader = new FileReader();
reader.onload = function(e) {
document.getElementById('preview').src = e.target.result;
document.getElementById('status').innerHTML = "Upload succesful";
ResizeImage();
};
reader.readAsDataURL(file);
}
});
});
function ResizeImage() {
if (window.File && window.FileReader && window.FileList && window.Blob) {
var filesToUpload = document.getElementById('imageFile').files;
var file = filesToUpload[0];
if (file) {
var reader = new FileReader();
// Set the image once loaded into file reader
reader.onload = function(e) {
var img = document.createElement("img");
img.src = e.target.result;
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0);
var MAX_WIDTH = 400;
var MAX_HEIGHT = 400;
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;
}
}
canvas.width = width;
canvas.height = height;
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0, width, height);
dataurl = canvas.toDataURL();
document.getElementById('output').src = dataurl;
}
reader.readAsDataURL(file);
}
} else {
alert('Not working so well in this browser');
}
}
</script>
</head>
<input id="imageFile" name="imageFile" type="file" class="imageFile" accept="image/gif, image/jpeg, image/png"/>
<br/>
<!--This 1x1 picture size workaround is a real flower-->
<img src="" id="preview" width="1" height="1">
<p id="status">status</p>
<img src="" id="output">

First Image is saving on second image upload?

I am trying to resize bulky image to reduce size image. For this i have implemented following code.
<html>
<head>
<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.2.1.min.js"></script>
</head>
<body>
<input type='file' id="fileUpload" />
<canvas id="canvas" width="450" height="300"></canvas>
</body>
<script type="text/javascript">
function el(id) {
return document.getElementById(id);
}
var canvas = el("canvas");
var context = canvas.getContext("2d");
function readImage() {
if ( this.files && this.files[0] ) {
var FR= new FileReader();
FR.onload = function(e) {
var img = new Image();
img.addEventListener("load", function() {
context.drawImage(img, 0, 0);
var MAX_WIDTH = 450;
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;
}
}
canvas.width = width;
canvas.height = height;
var ctx = canvas.getContext("2d");
ctx.mozImageSmoothingEnabled = true;
ctx.webkitImageSmoothingEnabled = true;
ctx.msImageSmoothingEnabled = true;
ctx.imageSmoothingEnabled = true;
ctx.drawImage(img, 0, 0, width, height);
});
img.src = e.target.result;
};
FR.readAsDataURL( this.files[0] );
} else {
alert("error");
return false;
}
var canvas = el("canvas");
var dataURL = canvas.toDataURL();
$.ajax({
type: "POST",
url: "http://localhost/newtry/lipak.php",
data: {
imgBase64: dataURL
}
}).done(function(o) {
console.log('saved');
});
}
el("fileUpload").addEventListener("change",readImage);
</script>
</html>
and in another php file i have a code to retrieve this code as follows
file_put_contents('photo.png', base64_decode(substr($_POST['imgBase64'], strpos($_POST['imgBase64'], ",")+1)));
but when i am uploading my first image its not getting saved. but after uploading another image first image got saved .. similarly second, third and so on.
So how can i retrieve an image on first attempt?
Vinay please call ajax in load function
function readImage() {
if ( this.files && this.files[0] ) {
var FR= new FileReader();
FR.onload = function(e) {
var img = new Image();
img.addEventListener("load", function() {
context.drawImage(img, 0, 0);
var MAX_WIDTH = 450;
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;
}
}
canvas.width = width;
canvas.height = height;
var ctx = canvas.getContext("2d");
ctx.mozImageSmoothingEnabled = true;
ctx.webkitImageSmoothingEnabled = true;
ctx.msImageSmoothingEnabled = true;
ctx.imageSmoothingEnabled = true;
ctx.drawImage(img, 0, 0, width, height);
$.ajax({
type: "POST",
url: "http://localhost/newtry/lipak.php",
data: {
imgBase64: dataURL
}
}).done(function(o) {
console.log('saved');
});
});
img.src = e.target.result;
};
FR.readAsDataURL( this.files[0] );
} else {
alert("error");
return false;
}
var canvas = el("canvas");
var dataURL = canvas.toDataURL();
}
el("fileUpload").addEventListener("change",readImage);
</script>

Upload two images into html5 canvas

I am trying to upload two and more images into one canvas and make some sort of collage. Pictures are the same size. However, when I try upload the second image, the first one disappears. Below there is the code and example to JSfiddle. What is wrong?
jsfiddle
<div>
<input type="file" id="imageLoader1" name="imageLoader" />
<br/>
<input type="file" id="imageLoader2" name="imageLoader" />
<br/>
<canvas id="canvas" style="background:red;"></canvas>
</div>
And JS code:
var imageLoader1 = document.getElementById('imageLoader1');
var imageLoader2 = document.getElementById('imageLoader2');
imageLoader1.addEventListener('change', handleImage, false);
imageLoader2.addEventListener('change', handleImage, false);
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
function handleImage(e) {
if (e.target == imageLoader1) {
var reader = new FileReader();
reader.onload = function (event) {
var img1 = new Image();
img1.onload = function () {
canvas.width = 1000;
canvas.height = 500;
ctx.drawImage(img1, 0, 0, img1.width, img1.height, 0, 0, img1.width * 0.4, img1.height * 0.4);
}
img1.src = event.target.result;
}
reader.readAsDataURL(e.target.files[0]);
}
if (e.target == imageLoader2) {
var reader = new FileReader();
reader.onload = function (event) {
var img2 = new Image();
img2.onload = function () {
canvas.width = 1000;
canvas.height = 500;
ctx.drawImage(img2, 0, 0, img2.width, img2.height, img2.width * 0.4, img2.height * 0.4, img2.width * 0.4, img2.height * 0.4);
}
img2.src = event.target.result;
}
reader.readAsDataURL(e.target.files[0]);
}
}
The idea was taken here: How to upload image into HTML5 canvas
When you are trying to superimpose multiple images in single canvas,You need to use two distinct paths, also you need to clearly circumscribe them with the .beginPath() method.
I have modified you code, please check. It should work for you.
function handleImage(e) {
if (e.target == imageLoader1) {
var reader = new FileReader();
reader.onload = function (event) {
var img1 = new Image();
img1.onload = function () {
canvas.width = 1000;
canvas.height = 500;
//added begin path here
ctx.beginPath();
ctx.drawImage(img1, 0, 0, img1.width, img1.height, 0, 0, img1.width * 0.4, img1.height * 0.4);
}
img1.src = event.target.result;
}
reader.readAsDataURL(e.target.files[0]);
}
if (e.target == imageLoader2) {
var reader = new FileReader();
reader.onload = function (event) {
var img2 = new Image();
img2.onload = function () {
canvas.width = 1000;
canvas.height = 500;
//added begin path here
ctx.beginPath();
ctx.drawImage(img2, 0, 0, img2.width, img2.height, img2.width * 0.4, img2.height * 0.4, img2.width * 0.4, img2.height * 0.4);
}
img2.src = event.target.result;
}
reader.readAsDataURL(e.target.files[0]);
}
}
Alternate :
Or what you can do is use globalAlpha property of canvas.
Try : ctx.globalAlpha = 0.5; .This may solve your issue.
Alternate 2:
You can use multiple canvas layer for multiple images. This will directly superimpose your images. You can superimpose as many images as you want.
I've modified original jsfiddle: click.
Here what have been changed:
var imageLoader1 = document.getElementById('imageLoader1');
var imageLoader2 = document.getElementById('imageLoader2');
imageLoader1.addEventListener('change', handleImage, false);
imageLoader2.addEventListener('change', handleImage, false);
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
let z = 0.4; // zoom
canvas.width = 1000;
canvas.height = 500;
function handleImage(e) {
if (e.target == imageLoader1) {
let img = new Image();
img.src = URL.createObjectURL(e.target.files[0]);
img.onload = function() {
ctx.drawImage(img, 0, 0, img.width, img.height, 0, 0, img.width * z, img.height * z);
}
}
if (e.target == imageLoader2) {
let img = new Image();
img.src = URL.createObjectURL(e.target.files[0]);
img.onload = function() {
ctx.drawImage(img, 0, 0, img.width, img.height, img.width * z, img.height * z, img.width * z, img.height * z);
}
}
}
I've moved canvas initialization out of load handler and simplified the loader.
This solution will not superimpose your images (but this is just a fix for original jsfiddle from the Question).

Categories

Resources