I have an issue with JavaScript when rendering an image before upload in a correct rotation. It seems that when you render the image witch have the correct rotation only on exif data the browser doesn't use it.
Users see a different rotation between what they have on their system on when image is displayed on the website by JavaScript.
The code is very basic:
Do you know a simple way to correct this rotation bug ?
LbEmeraude.handleImage = function (f) {
if (f.type.match('image.*')) {
var reader = new FileReader();
reader.onload = (function (file) {
return function (e) {
var image = {};
image.dataAsUrl = e.target.result;
LbEmeraude.renderImage(image);
};
})(f);
var image = reader.readAsDataURL(f);
}
}
LbEmeraude.renderImage = function (image) {
var eImage = LbEmeraude.createImgElement(image.dataAsUrl);
$('someElement').append(eImage);
};
LbEmeraude.createImgElement = function (src) {
var image = document.createElement("img");
image.src = src;
return image;
}
Thank for your attention.
What you are asking for is nothing new... check this out: https://bugzilla.mozilla.org/show_bug.cgi?id=298619
That sucker was opened in 2005 and has not been resolved yet. This article is old but really robust: http://www.daveperrett.com/articles/2012/07/28/exif-orientation-handling-is-a-ghetto/
But the key part in there is kinda far down where he notes that the browser does not usually apply exif rotation when in the context of an html img tag, but may honor it when opening the image in its own tab.
So right now no browser will do it by default, the web apps that seem to do it are mostly getting that value on the server and serving down different assets.
But it looks like there is hope if you want to hack it in: Accessing JPEG EXIF rotation data in JavaScript on the client side
Related
First to mention I am stuck in tinyMCE version 4.0.20 (For some stability issue I am not able to update the version in my project)
I have initiated tinyMCE editor and all necessary plugins. I need to have a image upload feature here (actually embed the image as data image). In that purpose what I have done the code so far would be found in this jsfiddle
Following is the file_browser_callback so far I have written.
function (field_name, url, type, window) {
var input = document.createElement('input');
input.setAttribute('type', 'file');
input.setAttribute('accept', 'image/*');
input.onchange = function () {
var file = this.files[0];
var reader = new FileReader();
reader.onload = function () {
var base64 = reader.result;
var image = new Image();
image.src = base64;
image.alt = file.name;
image.onload = function () {
/*
* just to work around I tried below to populate the fields.
* but for putting dimesions, I dont know how to do that. I
* think there should be some function or something in tinyMCE
* for that purpose
*/
window.document.getElementById(field_name).value = image.src;
$('input.mce-last', window.document).val(image.alt);
}
};
reader.readAsDataURL(file);
};
input.click();
}
I want to populate the popup fields with image title, description and dimensions from the image meta data. And you will notice there is a checkbox beside dimensions field Contains proportion that should work for maintain proportion from tinyMCE
I think the following image can help you understand.
Any help would be appreciated.
Okay, After wasting one another day I found the solution in tinyMCE forum. What actually I needed to do is to trigger a change on the url field and this will auto fill in it's width/height.
var fieldElement = window.document.getElementById(field_name);
fieldElement.value = image.src;
fieldElement.dispatchEvent(new Event('change'));
As I mentioned earlier I am stuck in an older edition of tinyMCE, this workaround is for the version 4.2 and earlier. For later version tinyMCE comes with a better approach of this. You will find the proper documentation here about the changes here
I read an image using the FileReader API, then I store the image as a blob in Indexeddb for later synchronization with a server. Until then I want to display a thumbnail of the image. It seems suboptimal to add the image ie. to a canvas element in full resolution and then resize it. It seems a better solution would be to resize it before adding it.
After synchronization I want to delete the full resolution image and only show the thumbnail. (My main concern is storage limits in a web app, on a mobile device)
Is it possible? and how?
Do not worry about adding extra stuff to the DOM, just do not do anything that will render it.
assuming you start with something along the lines of -
var reader = new FileReader();
reader.onload = function (e)
{
var img = new Image ;
img.src = e.target.result;
img.onload = function ()
then inside this onload function you can...
var canvas = document.createElement("canvas");
var context = canvas.getContext ("2d");
//draw it at any resolution you want
context.drawImage (this, 0, 0, width, height);
// read it back from the canvas, compressing if you want to
var saveData = canvas.toDataURL("image/jpeg",0.7);
// and save it where you want
// delete the canvas element unless you want to keep doing this regularly
I want to make a multiple images upload system with prograss bar. I want to do with simaple code(using jquery or js). I want when user has upload his images on browser and i want to show on browser that images and with upload button he starts uploading image via ajax in his folder.
So questions
1.) Is it possible to show uploaded image (without any complicated code) ?
2.) Do i get a variable or array where uploaded images are stored as base64 code (data:/img:dfd5d/d54fs..... something like this) or encoded?
3.) How do i add progressBar ?
I didn't write any code yet because i dont know how to start. I am new in computer science.
But i find this code on this site
function previewFile() {
var preview = document.querySelector('img');
var file = document.querySelector('input[type=file]').files[0];
var reader = new FileReader();
reader.onloadend = function () {
preview.src = reader.result;
}
if (file) {
reader.readAsDataURL(file);
} else {
preview.src = "";
}
}
This is easy code and i understand but one thing is not clear what does mean this line var reader = new FileReader(); why use new and what is it ?
Ty in advance and please dont explain complicate and i am not very good in english. So please try to explain in poor words if possible..
Assuming that you have this field
<input type="file" onchange="showImage(this)"/>
you can create a script to take the binary data and show it
function showImage(input){
var reader = new FileReader();
// validating...
var fileType = input.files[0].type;
var filesize = input.files[0].size;
// filetype (this will validate mimetype, only png, jpeg, jpg allowed)
var fileTypes = ["image/png", "image/jpeg", "image/gif"];
if (fileTypes.indexOf(fileType) < 0){
// return error, invalid mimetype
return false;
}
// file cannot be more than 500kb
if (filesize > 5000000) {
// return error, image too big
return false;
}
reader.onload = function (e) {
// e will contain the image info
jQuery('#myimagetopreview').attr('src', e.target.result)
}
reader.readAsDataURL(input.files[0]);
}
This should work, if you have problem tell me
edit: FileReader is not supported by all the browsers, check the documentation for more https://developer.mozilla.org/en/docs/Web/API/FileReader
The FileReader in JS has Status "Working Draft" and isn't part of the official JS API. I think you have to wait until the Browsers support this ne API or you have to activate experimental JS API in the Browser.
UPDATE:
For testing purposes, I used
<input type="text" onClick="doProcess(http://www.abc.com/chart.png)" />
That didn't work (used alert to test if url was being passed. The alert box did show up with the url, but decoding failed). In a sense, I answered a part of my question myself. Any ideas on how to read an image file through javascript?tt
Just found that this is HTML 5 related code. Also I figured since I'm passing a url instead of list of files, I'll need to remove the for() loop from the doProcess() function which would be
function doProcess(f)
{
var o=[];
var reader = new FileReader();
reader.onload = (function(theFile) {
return function(e) {
gCtx.clearRect(0, 0, gCanvas.width, gCanvas.height);
qrcode.decode(e.target.result);
};
})(f);
reader.readAsDataURL(f);
}
But this doesn't work too :(
ORIGINAL POST
I have an input file to which a QR image file is supplied with.
<input type="file" onchange="doProcess(this.files)">
doProcess function
function doProcess(f)
{
var o=[];
for(var i =0;i<f.length;i++)
{
var reader = new FileReader();
reader.onload = (function(theFile) {
return function(e) {
gCtx.clearRect(0, 0, gCanvas.width, gCanvas.height);
qrcode.decode(e.target.result);
};
})(f[i]);
reader.readAsDataURL(f[i]);
}
}
This function works perfectly. No problems there. The purpose of this function is to decode a QR image. Now out of sheer interest and curiosity, I'm planning to do something different - remove the need to browse to the image file manually. This brings me to a few queries:
Is it possible for doProcess(f) to perform the same actions when supplied with an image URL instead of a file? At present f parameter is a file. What will happen if f parameter is a URL (for ex: doProcess(http://www.abc.com/abc.jpg))? I realize there are other support functions inside doProcess() also being called to complete the decoding process but I'm assuming those will act accordingly to the type of data being passed through doProcess.
If f parameter is an image file (browsed on local computer and selected) instead of image URL, what data type will f be? I'm guessing it will be an array or in some raw binary form.
My intention is to study the process and know what exactly is happening behind the scenes. By using the 'browse' function, the QR image is being decoded successfully.
In summary, what will happen if I pass the location of the image stored as the argument instead of a file?
Thanks in advance.
There is some problems that I don't know you have or not in here because it's not your full code and I don't know what exactly you are trying to do. Here a working example of something very close of what you are doing. It loads a image on a canvas (you could use your qrcode stuff instead)
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
var gCanvas;
var gCtx;
function load(){
console.log("loaded");
gCanvas = document.getElementById("mcanvas");
if (gCanvas.getContext){
gCtx = gCanvas.getContext("2d");
} else console.log("no Canvas?");
}
function doProcess(f){
var o=[];
var reader = new FileReader();
reader.onload = (function(theFile) {
var img = new Image();
img.src = theFile;
img.onload = function(){
gCtx.clearRect(0, 0, gCanvas.width, gCanvas.height);
gCtx.drawImage(img,0,0);
}
return;
})(f);
console.log(reader);
reader.readAsDataURL(f);
}
</script>
</head>
<body onload="load()">
<input type="text" onClick="doProcess('https://www.google.com.br/logos/2012/clara_schuman-2012-hp.jpg')" />
<canvas id="mcanvas" height="500" width="500"></canvas>
</body>
</html>
dont't forget the load function, it grants your javascript to run after body loads.
Here's my sample code:
var input = document.createElement('input');
input.type = 'file';
document.body.appendChild(input);
input.addEventListener('change', function(){
var file = input.files[0];
var reader = new FileReader();
reader.onload = function(e){
var image = new Image();
image.src = e.target.result;
};
reader.readAsDataURL(file);
});
Load the page, select a large image (I'm using a 2.9MB 4288x3216 image). Refresh the page and select the same image. Result? The tab crashes! (Aw, Snap!)
My guess is that this is a bug with Chrome's implementation of the File API, but I'd love it if someone could confirm that and maybe even offer a workaround. I really want to be able to show a thumbnail of a photo without having to go to the server to generate one (even if it's just for Chrome and FF).
Also, with my sample code above, as soon as you select the photo, the tab starts using about 32MB more of memory. That, I guess, is expected, but what concerns me is that the memory never seems to get freed by the garbage collector. So if I keep selecting more photos, I keep consuming more memory. I don't know if this is related to the crashing issue or not, but it's definitely a concern.
Thanks for any help!
The memory issue could be a result of this bug: http://crbug.com/36142. Essentially, Chrome is caches data: URLs and currently does not release the memory when the img.src is changed. The other issue is that data: URLs yield a 33% overhead to the data you're encoding. That means you're actually setting a ~3.85MB resource on the image, not 2.9MB.
Since you're not manipulating the content (the actual bytes), there's no need to read the file content. One option is to create a blob: url. There's also an explicit revoke method, so you won't run into the same memory caching issues. Something like:
input.addEventListener('change', function(e) {
var file = input.files[0];
window.URL = window.webkitURL || window.URL; // Vendor prefixed in Chrome.
var img = document.createElement('img');
img.onload = function(e) {
window.URL.revokeObjectURL(img.src); // Clean up after yourself.
};
img.src = window.URL.createObjectURL(file);
document.body.appendChild(img);
});