In my angular application i have made image upload and preview using,
Html:
<input type='file' (change)="readUrl($event)">
<img [src]="url">
Ts:
readUrl(event:any) {
if (event.target.files && event.target.files[0]) {
var reader = new FileReader();
reader.readAsDataURL(event.target.files[0]);
reader.onload = (event: ProgressEvent) => {
this.url = (<FileReader>event.target).result;
}
}
}
As of now everything works fine..
But here the uploaded image is very bigger in size and hence i am in the need to implement auto crop and auto resize of the uploaded image that comes in preview, So that user can see the image in clear way..
Kindly help me to achieve the result of auto crop and resize without using jquery or any other libraries..
Stackblitz: https://stackblitz.com/edit/angular-a7ytbh
Edit:
Tried with javascript way https://jsfiddle.net/t3cgw65L/1/ but here only auto crop functionality is needed.. If we upload an image then only certain part is showing.. It needs to display the face if we upload our picture.. I am in need of uploading profile picture with auto crop and resize as like skype profile picture upload..
I updated your drawing function in jsfiddle:
function drawimg(idata) {
var img = new Image();
img.onload = function(){
canvas.width = 300; // defalt fixed size
canvas.height = this.height*canvas.width/this.width; // uploaded image aspect ratio
const ctx = canvas.getContext('2d');
ctx.drawImage(img, 0,0,canvas.width,canvas.height);
};
img.src = idata;
}
https://jsfiddle.net/t3cgw65L/2/
Let me know if it is what you want
Related
The situation is : I have to draw an image on canvas dynamically.
The code is :
HTML :
<canvas id="canvas" width="500px" height="300px"></canvas>
<input type="file" id="file-input">
jquery :
$(function() {
$('#file-input').change(function(e) {
var file = e.target.files[0],
imageType = /image.*/;
if (!file.type.match(imageType))
return;
var reader = new FileReader();
reader.onload = fileOnload;
reader.readAsDataURL(file);
});
function fileOnload(e) {
var $img = $('<img>', { src: e.target.result });
var canvas = $('#canvas')[0];
var context = canvas.getContext('2d');
$img.load(function() {
context.drawImage(this, 0, 0);
});
}
});
It adds the image to the top left corner. But now I might need to shift the image to another position by dragging and dropping. Also, I need to resize the image in similar way. For that I need to select the image (by getting reference to that image) on mouse click. I could have done that by checking if the mouse click coordinates overlaps with any image area. But if there are large number of images, this way will be inefficient (storing images in array and checking with each of them). Is there any more efficient way ?
PS : I am trying to build a UI designer which generates UI by dragging and dropping the elements in angular. I just started with the image element.
Edit 1 - I could use Fabric.js canvas instead. But still I would like to know if this can be done on native canvas too.
i'm working on a web app where you can upload an image, put a png image over, and download the image with the sticker applied.
For that i'm using html2canvas, and it's working fine, you upload your photo, choose the png and download the new image, so far everyting is fine, but if you want to change the png and download the new image it will dowload the first image again with the first png. Im checking and im creating everytime a new canvas, but evertyme the download button uses the first canvas. How could i refresh that canvas to donwload the last one everytime?
This is the code:
<script>
const capture = () => {
const body = document.querySelector('#ImagenLista');
body && (body.id = 'CapturaPantalla');
html2canvas(document.querySelector("#CapturaPantalla")).then(canvas => {
document.body.appendChild(canvas);
}).then(() => {
var canvas = document.querySelector('canvas');
canvas.style.display = 'none';
var image = canvas.toDataURL("image/jpg").replace("image/jpg", "image/octet-stream");
var a = document.createElement("a");
a.setAttribute('download', 'YoSoyYVoyA.jpg');
a.setAttribute('href', image);
a.click();
});
};
const btn = document.getElementById('DescargaImagen');
function FuncionDescarga() {
btn.addEventListener('click', capture);
}
</script>
Thank you so much.
I'm converting images to base64 using canvas. What i need to do is convert those images and then show the result to the user (original image and base64 version). Everything works as expected with small images, but when i try to convert large images (>3MB) and the conversion time increases, the base64 version is empty.
This might be is caused because the result is shown before the toDataURL() function is completed.
I need to show the result after all the needed processing has ended, for testing purposes.
Here's my code:
var convertToBase64 = function(url, callback)
{
var image = new Image();
image.onload = function ()
{
//create canvas and draw image...
var imageData = canvas.toDataURL('image/png');
callback(imageData);
};
image.src = url;
};
convertToBase64('img/circle.png', function(imageData)
{
window.open(imageData);
});
Even though i'm using image.onload() with a callback, i'm unable to show the result after the toDataURL() has been processed.
What am i doing wrong?
UPDATE: I tried both the solutions below and they didn't work. I'm using AngularJS and Electron in this project. Any way i can force the code to be synchronous? Or maybe some solution using Promises?
UPDATE #2: #Kaiido pointed out that toDataURL() is in fact synchronous and this issue is more likely due to maximum URI length. Since i'm using Electron and the image preview was for testing purposes only, i'm going to save the file in a folder and analise it from there.
Your code seems absolutely fine. Not sure why isn't working you. Maybe, there are some issues with your browser. Perhaps try using a different one. Also you could use a custom event, which gets triggered when the image conversion is competed.
// using jQuery for custom event
function convertToBase64(url) {
var image = new Image();
image.src = url;
image.onload = function() {
var canvas = document.createElement('canvas');
canvas.width = image.width;
canvas.height = image.height;
var ctx = canvas.getContext('2d');
ctx.drawImage(image, 0, 0);
var imageData = canvas.toDataURL();
$(document).trigger('conversionCompleted', imageData);
};
};
convertToBase64('4mb.jpg');
$(document).on('conversionCompleted', function(e, d) {
window.open(d);
});
This approach might work for you. It shows the image onscreen using the native html element, then draws it to a canvas, then converts the canvas to Base64, then clears the canvas and draws the converted image onto the canvas. You can then scroll between the top image (original) and the bottom image (converted). I tried it on large images and it takes a second or two for the second image to draw but it seems to work...
Html is here:
<img id="imageID">
<canvas id="myCanvas" style="width:400;height:400;">
</canvas>
Script is here:
var ctx;
function convertToBase64(url, callback)
{
var image = document.getElementById("imageID");
image.onload = function() {
var canvas = document.getElementById("myCanvas");
canvas.width = image.naturalWidth;
canvas.height = image.naturalHeight;
ctx = canvas.getContext("2d");
ctx.drawImage(image,0,0);
var imageData = canvas.toDataURL('image/png');
ctx.fillStyle ="#FFFFFF";
ctx.fillRect(0,0,canvas.width,canvas.height);
callback(imageData);
};
image.src = url;
};
var imagename = 'images/bigfiletest.jpg';
window.onload = function () {
convertToBase64(imagename, function(imageData) {
var myImage = new Image();
myImage.src = imageData;
ctx.drawImage(myImage,0,0);
});
}
Note that I also tried it without the callback and it worked fine as well...
I have an html canvas that shows a preview of an image when the image is selected in an input. This works in Chrome, but I can't seem to get it to work in Safari. Specifically - in Safari - the onchange="previewFile()" does not seem to call the previewFile function.
<canvas id="canvas" width="0" height="0"></canvas>
<h2>Upload a photo </h2>
<input type="file" onchange="previewFile()"><br>
<script type="text/javascript">
// setup the canvas
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
// grab the photo and display in canvas
var photo = new Image();
function previewFile() {
var file = document.querySelector('input[type=file]').files[0];
var reader = new FileReader();
reader.addEventListener("load", function () {
photo.src = reader.result;
canvas.height = photo.height;
canvas.width = photo.width;
ctx.drawImage(photo,0,0);
}, false);
if (file) {
reader.readAsDataURL(file);
}
}
</script>
Your problem is certainly due to the fact that you are not waiting for the image has loaded before you try to draw it on the canvas.
Even wen the source is a dataURI, the loading of the image is asynchronous, so you need to wrap your drawing operations in the image's onload event.
var photo = new Image();
photo.onload = function(){
canvas.height = photo.height;
...
}
...
reader.onload = function(){
// this will eventually trigger the image's onload event
photo.src = this.result;
}
But if all you need is to draw your image on the canvas, don't even use a FileReader, actually, the readAsDataURL() method should trigger a I'm doing something wrong error in your brain. Almost all you can do with a dataURI version of a Blob, you can also do it with the Blob itself, without computing it nor polluting the browser's memory.
For example, to display an image for user input, you can use URL.createObjectURL(blob) method.
// setup the canvas
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
// grab the photo and display in canvas
var photo = new Image();
// drawing operations should be in the mage's load event
photo.onload = function() {
// if you don't need to display this image elsewhere
URL.revokeObjectURL(this.src);
canvas.height = this.height;
canvas.width = this.width;
ctx.drawImage(this, 0, 0);
}
photo.onerror = function(e) {
console.warn('file format not recognised as a supported image');
}
file_input.onchange = function() {
// prefer 'this' over DOM selection
var file = this.files[0];
var url = URL.createObjectURL(file);
photo.src = url;
};
<canvas id="canvas" width="0" height="0"></canvas>
<h2>Upload a photo </h2>
<input type="file" id="file_input">
<br>
And for those who need to send this file to their server, use a FormData to send directly the Blob. If you really need a dataURI version, then convert it server-side.
Im writing app in html5 that needs to be work on cell phones,
this app uploads an image from the phone to server of my company.
Now its working on android and inthe computer, on Iphone its work only when i picture in the front camera, if i get a pic from the back camera I get empty data.
I create an InputElement type file,
and event onChange for the input element, that call the function inputFile_onChange that get an ElementEvent el:
var file = el.target.files[0];
var reader = new FileReader();
reader.onloadend = (function(theFile) {return function(e) {
$('#uploadImage').attr('src',e.target.result);
$('#uploadImage').css('display','none');
$($('#uploadImage')[0]).one('load',function(){
var cvs = document.createElement('canvas');
$image = $('#uploadImage')[0];
var savingCanvas = document.createElement('canvas');
savingCanvas.width = $image.naturalWidth;
savingCanvas.height = $image.naturalHeight;
var savingCanvasCtx = savingCanvas.getContext('2d');
FileUploadApp._globals.drawImage(savingCanvasCtx, $image, 0, 0,
savingCanvas.width,savingCanvas.height);
var newImageData = savingCanvas.toDataURL('image/jpeg', 0.2);
}).each(function() {if(this.complete) $(this).load();});
};
})(file);
reader.readAsDataURL(file);
I put an alert after the newImageData create and get "data: ," when i look for answer in the web i see that i get this if canvas sizes are 0, but i also print the size - width and hight and both of them are big >1000
Ill be glad to get some help with it.
I found the problem,
the function canvas.toDataURL return nothing when the canvas is big,
I shrink the canvas to 1000 pix and the problem solved