How do I only accept photos (from the file explorer) smaller that 1920x1080. Otherwise, my entire webpage get flooded with one image. Here is my code for importing the photos:
Html:
<input type="file" id="file" accept="image/png, img/jpeg">
Javascript:
function Read(){
var file = document.getElementById("file").files[0];
var reader = new FileReader();
reader.onload = function(e) {
var image = document.createElement("img");
// the result image data
image.src = e.target.result;
document.body.appendChild(image);
}
reader.readAsDataURL(file);
}
You can use Canvas to resize bigger images.
<input type="file" id="file" accept="image/png, img/jpeg" #change="selectFile">
selectFile: function (list)
{
const self = this, limitWidth = 1920, limitHeight = 1080, len = list.length;
let i, item, cnt = len;
events.$emit('show_spinner');
for(i=0;i<len;i++)
if(list[i].size)
{
item = list[i];
const reader = new FileReader(), img = new Image(), canvas = document.createElement('canvas');
reader.onload = function (e)
{
img.v_name = this.v_name;
img.v_size = this.v_size;
img.src = e.target.result;
};
reader.onerror = function ()
{
events.$emit('hide_spinner');
};
img.onerror = function ()
{
events.$emit('hide_spinner');
};
img.onload = function ()
{
canvas.width = img.naturalWidth;
canvas.height = img.naturalHeight;
// preserve aspect ratio
if(canvas.width > limitWidth)
{
canvas.width = limitWidth;
canvas.height = limitWidth * img.naturalHeight / img.naturalWidth;
}
if(canvas.height > limitHeight)
{
canvas.height = limitHeight;
canvas.width = limitHeight * img.naturalWidth / img.naturalHeight;
}
// implicit width and height in order to stretch the image to canvas
canvas.getContext("2d").drawImage(img, 0, 0, canvas.width, canvas.height);
self.fileArray.push(
{
name: this.v_name,
size: this.v_size,
src: canvas.toDataURL('image/jpeg', 0.8),
id: Date.now()
}
);
cnt--;
if(cnt==0) events.$emit('hide_spinner');
};
reader.v_name = item.name;
reader.v_size = item.size;
reader.readAsDataURL(item);
}
},
You don't need to check the image size. you can just use css for resizing the image so it doesn't fill up the page.
img {
width: 100%;
max-width: 300px;
/** height will be automatically calculated */
}
this way images won't be wider than 300 pixels and they won't fill up your entire page.
Related
I am working on image compression and I have a requirement to compress the photo if the image size is greater than 2MB.
Use case:
If the size is 1.9MB do nothing
If the size is 3MB or 5MB or 10MB then compress the image so that its size is less than 2MB always. (I am having trouble with this one)
If there is any solution, I would appreciate it.
$("#photo").change(function () {
var reader = new FileReader();
reader.onload = (e) => {
const imgElement = document.createElement("img");
imgElement.src = event.target.result;
document.querySelector("#input").src = event.target.result;
imgElement.onload = function (evt) {
console.log(evt);
const canvas = document.createElement("canvas");
const MAX_WIDTH = 400;
const scaleSize = MAX_WIDTH / evt.target.width;
canvas.width = MAX_WIDTH;
canvas.height = evt.target.height * scaleSize;
const ctx = canvas.getContext("2d");
ctx.drawImage(evt.target, 0, 0, canvas.width, canvas.height);
const srcEncoded = ctx.canvas.toDataURL(evt.target, "image/jpeg");
document.querySelector("#output").src = srcEncoded;
reader.onload = () => srcEncoded = reader.result;
}
reader.readAsDataURL(this.files[0]);
});
I'm trying to resize an image in the client side and then send it to my server. But the image is not all the times settled correctly to the canvas used to resize the image.
I already sent the image resize but i need to send it at least 2 times to work.
I put <p> labels in my html to verify the data of the image and i can see the data incomplete the first time i send it.
This is my html
function ResizeImage() {
var filesToUpload = document.getElementById('imageFile').files;
var file = filesToUpload[0];
console.log('Data');
// Create an image
var img = document.createElement("img");
// Create a file reader
var reader = new FileReader();
// Set the image once loaded into file reader
reader.onload = function(e) {
//HERE IN THIS PART, the e.target.result works strange
img.src = e.target.result;
var canvas = document.createElement("canvas");
//var canvas = $("<canvas>", {"id":"testing"})[0];
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0);
// var MAX_WIDTH = 400;
// var MAX_HEIGHT = 400;
var width = 200;
var height = 200;
if (img.width > img.height) {
if (img.width > width) {
height *= height / img.width;
//width = width;
}
} else {
if (img.height > height) {
width *= height / img.height;
//height = height;
}
}
canvas.width = width;
canvas.height = height;
ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0, width, height);
var dataurl = canvas.toDataURL("image/png");
console.log(dataurl);
canvas.toBlob((blob) => {
var fd = new FormData();
fd.append("name", "paul");
fd.append("image", blob);
fd.append("key", "××××××××××××");
var xhr = new XMLHttpRequest();
xhr.open("POST", "http://localhost:5000/2");
xhr.send(fd);
}, "image/png", 1)
document.getElementById('output').src = dataurl;
var para = document.createElement("p");
var node = document.createTextNode(dataurl);
para.appendChild(node);
var element = document.getElementById("contenedor");
element.appendChild(para);
}
// Load files into file reader
reader.readAsDataURL(file);
}
<input type="text" name="fileName">
<input type="file" id="imageFile" name="sampleFile" accept="image/png" />
<input type='button' value='Upload!' onclick="ResizeImage()" />
<img src="" id="output">
<div id="contenedor"></div>
<hr>
I expect it works the first time i send the data to the server.
Img.src is asynchronous.
To verify this, replace 'img.src = e.target.result;' with
img.onload = function () { console.log('done')}
img.src = e.target.result;
console.log('src')
If done runs after src, you know that the image isn't loaded yet when you try to ctx.drawImage.
To fix, simply move all your resizing code into img.onload.
I'm newbie in JS and React. I am using React and I have multiple file input in a form, I wish if the user select image the images should be resized and previewed before user click upload. Now the resizing, previewing and uploading are all fine, the problem is when I change a file input, the other file inputs preview and upload are all changed synchronously! any help will be appreciated.
This is the code:
render():
render(){
return(
...
<label>Image1
<input type="file" id="img1" on Change={this.handleChange} />
</label>
<br/>
<img id="img1_preview" src="" height="100" />
<label>Image2
<input type="file" id="img2" on Change={this.handleChange} />
</label>
<img id="img2_preview" src="" height="100" />
...
)
}
function():
...
handleChange(event) {
...
/* handle all image input change */
if (event.target.id.includes('img')) {
var field = event.target.id;
var preview = document.getElementById(field + '_preview');
var file = event.target.files[0];
var reader = new FileReader();
reader.onload = function(readerEvent) {
var image = new Image();
image.onload = function(imageEvent) {
var canvas = document.createElement('canvas');
var max_size = 800; /* max size */
var 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);
var dataUrl = canvas.toDataURL('image/jpeg');
/* Utility function to convert a canvas to a BLOB */
var dataURLToBlob = function(dataURL) {
var BASE64_MARKER = ';base64,';
if (dataURL.indexOf(BASE64_MARKER) === -1) {
var parts = dataURL.split(',');
var contentType = parts[0].split(':')[-1];
var raw = parts[1];
return new Blob([raw],{type:contentType});
}
var parts = dataURL.split(BASE64_MARKER);
var contentType = parts[0].split(':')[1];
var raw = window.atob(parts[1]);
var rawLength = raw.length;
var uInt8Array = new Uint8Array(rawLength);
for (var i = 0; i < rawLength; ++i) {
uInt8Array[i] = raw.charCodeAt(i);
}
return new Blob([uInt8Array],{type:contentType});
}
/* End Utility function to convert a canvas to a BLOB */
var resizedImage = dataURLToBlob(dataUrl);
$.event.trigger({
type: "imageResized",
blob: resizedImage,
url: dataUrl
});
}
image.src = readerEvent.target.result;
}
reader.readAsDataURL(file);
$(document).on("imageResized",function(event1){
if (event1.blob && event1.url) {
var blob = event1.blob, url = event1.url;
# set state, later will be submit to server
this.setState({[field]:blob});
/* preview */
var reader1 = new FileReader();
reader1.addEventListener("load",function(){
preview.src = url;
}, false);
reader1.readAsDataURL(blob);
/* end preview */
}
})
}
the page:
the page image
thanks #Kaiido, according to his advise, the problem has been solved(although I don't know the exact reason).
this is the working code:
...
handleChange(event) {
...
/* handle all image input change */
if (event.target.id.includes('img')) {
var field = event.target.id;
var preview = document.getElementById(field + '_preview');
var file = event.target.files[0];
var reader = new FileReader();
reader.onload = function(readerEvent) {
var image = new Image();
image.onload = function(imageEvent) {
var canvas = document.createElement('canvas');
var max_size = 800; /* max size */
var 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);
var dataUrl = canvas.toDataURL('image/jpeg');
/* changed code */
canvas.toBlob(function(blob){
this.setState({[field]:blob});
var reader1 = new FileReader();
reader1.addEventListener("load",function(){
preview.src = dataUrl;
}, false);
reader1.readAsDataURL(blob);
});
/* end changed */
}
image.src = readerEvent.target.result;
}
reader.readAsDataURL(file);
}
I have created a image select and resize (Client side) and upload to server. What I am asking for help is with image preview in iframe(resized) but cannot figure out. I will be only using Chrome desktop for this application. Qusetion is please help me with displaying resized image within my iframe here are my scripts below
HTML
<input type="file" input id="input" onchange="ClientSideResize()" name="Image" value="%%%img%%%"/>
HTML iframe
<img src="" id="image">
<iframe name="my_iframe" src="" id="my_iframe" style="visibility: hidden;"></iframe>
SCRIPT
<script>
function ClientSideResize(){
var dataurl = null;
var uniq = 'id' + (new Date()).getTime();
var filesToUpload = document.getElementById('input').files;
var file = filesToUpload[0];
// Create an image
var img = document.createElement("img");
// Create a file reader
var reader = new FileReader();
// Set the image once loaded into file reader
reader.onload = function(e)
{
img.src = e.target.result;
img.onload = function () {
canvas = document.createElement("canvas");
ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0);
var MAX_WIDTH = 200;
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("image/jpeg",100);
var blobBin = atob(dataurl.split(',')[1]);
var array = [];
for(var i = 0; i < blobBin.length; i++) {
array.push(blobBin.charCodeAt(i));
}
files = new Blob([new Uint8Array(array)], {type: 'image/jpg', name: "Sample"});
} // img.onload
}
// Load files into file reader
reader.readAsDataURL(file);
}
</script>
Giving you a few other tips along the way... filereader is not the preferred way. and the way you build your blob afterwards is no good, use canvas#toBlob directly instead.
function ClientSideResize () {
// var uniq = 'id' + Date.now() // never used
var filesToUpload = document.getElementById('input').files
var file = filesToUpload[0]
// Create an image
var img = new Image
img.onload = () => {
const MAX_WIDTH = 200
const MAX_HEIGHT = 400
var canvas = document.createElement('canvas')
var ctx = canvas.getContext('2d')
var width = img.width
var height = img.height
// figure out new width and hight while keeping proportionally
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
}
}
// set diminsion
canvas.width = width
canvas.height = height
// draw resized image
ctx.drawImage(img, 0, 0, width, height)
// get it as a blob
canvas.toBlob(blob => {
// Do something with blob
// let file = new File([blob], 'filename.png', {type: blob.type})
let iframe = document.querySelector('iframe')
iframe.contentWindow.postMessage(blob, '*')
}, 'image/jpeg', 100)
} // img.onload
img.src = URL.createObjectURL(file)
}
// on iframe
window.onmessage = event => {
console.log(event) // will contain your blob object
}
Im using the code below to draw and scale an image inside a canvas. The issue being that the image rendered inside is stretched to fit.
If possible, I would like it to be scaled based on width but to maintain its aspect ratio.
Any ideas?
//IMAGE LOADER
var canvas = document.getElementById('image-canvas');
var canvas2 = document.getElementById('image-canvas2');
ctx = canvas.getContext('2d');
ctx2 = canvas2.getContext('2d');
// Trigger the imageLoader function when a file has been selected
var fileInput = document.getElementById('fileInput');
fileInput.addEventListener('change', imageLoader, false);
function imageLoader() {
var reader = new FileReader();
reader.onload = function(event) {
img = new Image();
img.onload = function(){
ctx.drawImage(img,0,0,canvas.width, canvas.height);
ctx2.drawImage(img,0,0,canvas.width, canvas.height);
}
img.src = reader.result;
}
reader.readAsDataURL(fileInput.files[0]);
}
You can figure out dimensions of the image by adding it to the DOM. Once you know the ratio, you can scale your image to fit within your canvas.
ratio = width / height;
width = height * ratio;
height = width / ratio;
The following should work whether an image is landscape or portrait.
var canvas = document.getElementById('image-canvas');
var canvas2 = document.getElementById('image-canvas2');
var ctx = canvas.getContext('2d');
document.getElementById('fileInput').addEventListener('change', imageLoader, false);
function imageLoader() {
var reader = new FileReader();
reader.onload = function(event) {
var img = new Image();
img.onload = function(){
var ct = document.getElementById('measure');
ct.appendChild(img);
var wrh = img.width / img.height;
var newWidth = canvas.width;
var newHeight = newWidth / wrh;
if (newHeight > canvas.height) {
newHeight = canvas.height;
newWidth = newHeight * wrh;
}
ct.removeChild(img);
ctx.drawImage(img,0,0, newWidth , newHeight);
}
img.src = reader.result;
}
reader.readAsDataURL(fileInput.files[0]);
}
/* Add image to the DOM here so user can't see it */
#measure { position: absolute; left: -10000px; top: -100000px;}
canvas { border: 1px solid red; }
<canvas id="image-canvas" width="300" height="300"></canvas>
<input type="file" id="fileInput" />
<div id="measure"></div>
You can play with it here