getting size of image from a link as dynamic content - javascript

I want to make an image previewer inside a page. I will have a "div" to include smaller images by setting the size of "img" by hand. Then clicked or hovered, the image will show on a bigger "div", as small as the image itself or as big as window view size near the mouse pointer. the code will have only image link and will get actual image size from there.
setting the size and position of previewer "div" is just a mathematical problem for me. but I can't seem to find how to get image size by the link. I tried only to get mostly undefined values if not errors.
Be careful while answering that most of the thought methods get the size from the "img" element itself if sizes are set, but returns null if not.
CAUTION: this is similar to How to get image size (height & width) using JavaScript? , but (a) accepted answer does not work for me. it gives either 0x0 or undefined. (b) suggested answer of Josh Stodola works only if image loaded with window. my link is dynamic.
this is also similar to Get width height of remote image from url. It works with alert function, but I cant get the size out of the said functions as I need them for calculations.

I updated my answer. It now triggers on a mouseover event and doesn't use an ID. Be sure to accept the answer if this is working for you.
function getMeta(imageSrc,callback) {
var img = new Image();
img.src = imageSrc;
img.onload = function() { callback(this.width, this.height); }
}
function hoverLink(imageSrc){
getMeta(
imageSrc,
function(width, height) {
document.getElementById("prev").innerHTML = width + 'px ' + height + 'px';
}
);
}
function hoverOff(){
document.getElementById("prev").innerHTML ='';
}
<a href="https://res.cloudinary.com/rss81/image/upload/gw.jpg"
onmouseover="hoverLink(this.href)"
onmouseout="hoverOff()">
Picture Link
</a>
<div id='prev'></div>

Thanks to #dcr, I got the problem over. He helped me with the code, and I have seen the problem that confused me.
Those answers to other posts mostly used "alert" function, which is not a good way to show how to get required value, in my case the size of an image.
Here in this code, it can clearly be seen that "getMeta" and "caller" functions are merely an interface to "setter". I can reference any required value from "callback" part and "setter" can then be expanded to the needs, in my case calculating the size and position of my previewer "div". The only difference with #dcr 's solution is getting the "setter" function out of "caller" function.
function getMeta(imageSrc,callback) {
var img = new Image();
img.src = imageSrc;
img.onload = function() { callback(this.width, this.height); }
}
function caller(imageSrc){
getMeta( imageSrc,setter);
}
function setter(width, height) {
document.getElementById("prev").innerHTML = width + 'px X ' + height + 'px';
}
Picture Link
<div id='prev'></div>

Related

How to view an image file's dimension with javascript

I'm trying to assign variables that store the height and width of an image from the local "img" folder. I tried something along the lines of
myWidth = (("img/myImage.png").naturalWidth);
but as far as I can tell, that only works if the image is already present somewhere on the page. Is there a way to do this by getting Javascript to view the file's properties in the folder?
EDIT: I'm not doing anything too technical. I just have 600 or so small images that need to be in separate divs that are the same pixel width and height as the image, and each image is different. I'm trying to write a script to generate all the code for my css without having to type it all in manually.
You can use an Image element to get the dimensions. I have previously created a tool that fetches image dimensions via JavaScript for an SO question. You can see it in action here: https://codepen.io/NikxDa/pen/apegZa
Necessary part:
var img = new Image ();
// Handle onload (will contain data after file has loaded)
img.onload = function () {
alert ("The dimensions are: " + this.width + "x" + this.height);
};
// Load the file by fileUrl
img.src = <fileUrl>;
Hope it helps.

Display image after file input selection with image resize

I have seen posts asking how to display an image selected via a file input control. When I try these solutions, they work, yet I have a further issue I am unable to discover an answer to on my own: When I select an image for the first time, the image will not display because no image width and height data is available (image data is available via the FileReader obj, yet not the image width and height). The second time the image is selected (or after a reload), the width and height become available. Why is this occurring and what can I do to fix it? thanks.
Here's some code I've been using - this is one of the FileReader functions. I started by using reader.onload, but then thought the image width and height were not available because it hadn't loaded fully yet. Therefore onloadend seemed a better choice. It doesn't work any better here, though:
reader.onloadend = function(e) {
var img = new Image();
img.src = e.target.result;// or reader.result - doesn't matter
// A function that does math to proportionally scale the image
var new_size = scaleImageSize(150, 150, img.width, img.height);
img.width = new_size[0];
img.height = new_size[1];
// And here I am trying both ways to display the image: the first
// in a div tag, the second straight into an img tag. I only want
// to use one of these - preferably the div tag. I have also tried
// drawing the image onto an HTML5 canvas. All to no avail.
document.getElementById("file_display_area").appendChild(img);
document.getElementById("img_file_display_area").src = img.src;
console.log(img.width + '|' + img.height + '||' + new_size[0] + '|' + new_size[1]);
}

Wrong width and height when reusing FileReader

I am currently developing a simple interface allowing users to upload a picture, have a preview of it, and then be able to crop it as a square.
I'm using FileReader to get the preview of the image, and jCrop to crop it.
Here is the code I'm using (a part of it):
var jcrop = null;
var reader = new FileReader();
reader.onload = function (e) {
$('#upload-picture-sample').attr('src', e.target.result).load(function(){
var img = this;
var imageWidth = img.width;
var imageHeight = img.height;
console.log(img.width+'-- WIDTH --'+$(this).width());
console.log(img.height+'-- HEIGHT --'+$(this).height());
if(imageWidth != imageHeight){
var selectArray = [];
if(imageWidth > imageHeight){
selectArray = [(imageWidth-imageHeight)/2, 0, (imageWidth-imageHeight)/2 + imageHeight, imageHeight];
}else{
selectArray = [0, (imageHeight - imageWidth)/2, imageWidth, (imageHeight - imageWidth)/2 + imageWidth];
}
if(!jcrop){
$('#upload-picture-sample').Jcrop({
aspectRatio: 1,
keySupport: false,
addClass: 'jcrop-centered',
setSelect: selectArray
}, function(){
jcrop = this;
});
}else{
jcrop.setImage(e.target.result);
jcrop.setSelect(selectArray);
}
}
$(this).unbind('load');
});
}
$('#upload-picture-file').change(function(){
$('#upload-picture-send').removeClass('disabled');
$('#upload-picture-error').hide();
console.log('changed!');
reader.readAsDataURL(this.files[0]);
})
I think the only part that really matters is the part when I calculate the width and height.
To illustrate the problem, I'm uploading:
1/ Picture1 (600x450)
2/ Picture2 (94x125)
3/ Picture1 again (600x450)
The first upload is working fine, the second is working fine as well, but I guess it's more luck than something else, since the height is incorrectly calculated as 0.
The third upload is not working (the size is not correctly set).
It means that the cropzone is not correctly displayed.
Regarding css, I have this:
#upload-picture-sample{
display:block;
margin-left: auto;
margin-right: auto;
margin-bottom: 30px;
max-height:125px;
height:auto;
width:auto;
max-width:300px;
}
Do you have any idea of how I could solve my problem?
UPDATE: After having added setTimeout as recommended by #initialxy
So it's much better, but still, the first image doesn't have the same dimensions than the last (and it should, since it's exactly the same image)
Thanks.
All of your numbers look inconsistent. In first image, width end up being 167 with img.width but 167 with jQuery. One thing to note is that jQuery gets computed style while img.width and img.height are DOM properties that sets desired width and height. (FYI there's also naturalWidth and naturalHeight, which are read-only DOM properties that gets you the original dimensions of img.)
it's more luck than something else
If your code depends on luck, then we got a problem.
It looks like browser emitted load event slightly too early, such that layout engine hasn't finished updating the DOM. load just means data is loaded, doesn't necessarily mean layout engine has to be completed. So try to queue your code block inside your load function later in the task queue. By which, I mean wrap all that in a setTimeout(..., 0); Watch out for this, as it has changed.
eg.
$('#upload-picture-sample').attr('src', e.target.result).load(function(){
var img = this;
setTimeout(function() {
var imageWidth = img.width;
var imageHeight = img.height;
console.log(img.width+'-- WIDTH --'+$(img).width());
console.log(img.height+'-- HEIGHT --'+$(img).height());
// TODO: Crop
...
}, 0);
$(this).unbind('load');
});
EDIT: In response to #Vico's update. Looks like layout engine has settled this time. Let's make some observations on these numbers. The first image's dimensions were originally 600x450, but it ended up being 167x125. This makes sense, because it was resized by max-height: 125px; CSS property. The second image has both of its dimensions less than max-width and max-height so it didn't get resized. The third image has dimensions of 600x450, and it ended up having these dimensions, so at this point max-width and max-height is no longer taking effect. Why is that? Perhaps jcrop screwed around with style and overridden your style. Fire up your Chrome debugger, inspect your img element and use its JavaScript console to play around with it. (To give you a short answer, yes, jcrop does screw around with style and applies inline styles to the element, which overrides your style. But hey, it's more fun to play with debugger.) Also, I'm not sure why your dimensions on the right all ended up with 1440x514. You can find out by screwing around in debugger.
For more information, I suggest all the potential readers to have a look at this issue:
https://github.com/tapmodo/Jcrop/issues/46
The workarounds work fine.

Get image dimensions after resizing

I have encountered a problem that other people had in this website before but none of the solutions helped me slightly.
I have a method that updates an image inside a div (read: user uploads a new image) where the image is resized to fit the set proportions (max-height and max-width are 45x45). I have to resize the div that holds the image to 2* it's dimensions such as the example below:
Original image is 180x180.
It is resized to 45x45. Div has to be 90x90.
Code is as follows:
function uploadThumbnail(id, xCoord, yCoord) {
var oFReader = new FileReader();
oFReader.readAsDataURL(document.getElementById("thumbnailLoader"+id).files[0]);
oFReader.onload = function(oFREvent) {
var mapThumbnail = updateMapThumbnail(oFREvent.target.result, id);
var mapContainer = document.getElementById("thumbnail"+id);
var informationContainer = document.getElementById("container"+id);
console.log(mapThumbnail.width);
mapContainer.removeChild(document.getElementById("mapThumbnail"+id));
informationContainer.removeChild(document.getElementById("infoThumbnail"+id));
informationContainer.insertBefore(updateInfoThumbnail(oFREvent.target.result, id), informationContainer.firstChild);
mapContainer.appendChild(mapThumbnail);
};
};
function updateMapThumbnail(result, id){
var newThumbnail = document.createElement("img");
newThumbnail.src = result;
newThumbnail.style.maxWidth = "45px";
newThumbnail.style.maxHeight = "45px";
newThumbnail.id = "mapThumbnail" + id;
return newThumbnail;
}
As you can see I added a console.log method there for test purposes. The problem I am facing is that generating mapThumbnail with set max dimensions (45x45) still has the height and width attributes set with the original image size. I tried reading image.height/width and image.style.height/width as well as naturalHeight/width and clientHeight/width.
None of these solutions return the height and width after resizing.
Thanks for your time.
Also, please refrain from offering solutions that require JavaScript libraries.
Edit: forgot to mention that the image placed inside the div is re-sized to the dimensions that I do want it to be. It's just the attributes that seem to be wrong.
There are four different and undependant widths on an image:
1) img.naturalWidth is the width in px the original image file has. It doesn't change when you set the other widths to some value. This value is rendered when the others are not defined.
2) img.width is an attribute of img. You find it inside the html img tag and can set it with img.setAttribute('width', 'value'). It doesn't change when the others are set to some value. This value is rendered when 3) is not defined and 4) is >= img.width or not defined.
3) img.style.width is a css-property of the images style. You can set it in your css or into the style-attribute in the img tag with img.style.width = 'value';. It doesn't change when the others are set to some value. This value is rendered when it is <= 4) or 4) is not defined.
4) img.style.max-width is another css-property of images style. You can set it in your css or into the style-attribute in the img tag with img.style.maxWidth = 'value';. It doesn't change when the others are set to some value. This is rendered when 2) or 3) are not defined or have values > 4).
So you have to decide by yourself which value you want to receive or set.
Its the same with height, there are also four heights.
EDIT According to your comment:
Inside your function updateMapThumbnail you create a new img. A newly created img has no .width unless you define it with newThumbnail.setAttribute('width', 'value). Same with img.style.width: unless you set it explicitely somewhere it's simply not there.
Did you try:
console.log(getComputedStyle(mapThumbnail).width);

Javascript: Images loading too slowly

I have an array of images that I create dialogs from.
I need to know the width of the image to make that the width of the dialog.
//Used to get dimensions of image
var image = new Image();
//Set Image
image.src = ImageArray[currentImageVal + direction].src;
//Get direction to move photos
switch (direction) {
case 1:
//Set current val
currentImageVal = currentImageVal + 1;
break;
case -1:
//Set current val
currentImageVal = currentImageVal - 1;
break;
}
//Set image
$('DialogImagesBig').attr('src', ImageArray[currentImageVal].src);
//Set new current image
CurrentDialogImage = ImageArray[currentImageVal].src;
console.log(image.src);
console.log(image.width);
//Check if it is less than 450
if (image.width < 450) {
//Adjust css
$('.ui-dialog').css('width', image.width + 50);
//Edit dialog position
$('.ImageDialogDiv').dialog("option", "position", 'center');
} else {
//Normal width
$('.ui-dialog').css('width', '500');
//Edit dialog position
$('.ImageDialogDiv').dialog("option", "position", 'center');
}
The problem is that more times then not the image will not load up in time (the console.log(image.width) will equal 0 but console.log(image.src) will be correct).
Is there a way for me to pause the rest of the script until the image is loaded (everything after image.src)?
You can attach rest of the code in img.onload function. This will get called when the image gets loaded.
Make sure you set the image.src after this function declaration.
image.onload = function () {
if (image.width < 450) {
//Adjust css
$('.ui-dialog').css('width', image.width + 50);
//Edit dialog position
$('.ImageDialogDiv').dialog("option", "position", 'center');
} else {
//Normal width
$('.ui-dialog').css('width', '500');
//Edit dialog position
$('.ImageDialogDiv').dialog("option", "position", 'center');
}
}
image.src = ImageArray[currentImageVal + direction].src;
Using onload event may be problematic with ie, in some circumstances - see comments here: http://msdn.microsoft.com/en-us/library/cc197055(v=vs.85).aspx -- even if the image is created in code, if it's already cached, it may not fire. This may only apply to IE6-7.
So in addition to doing this, you should check first to see if it's finished loading before binding the event using the naturalWidth and complete (for old IE) properties. naturalWidth (and height) will be undefined until the image has loaded.
I can conceive of a race condition if you check first to see if it's loaded, then if not, bind the "onload" event, but between these two actions, the image finishes loading. I am not sure if this is possible given JS's single-threaded nature, but since images are loaded asynchronously, perhaps it is.
In a project where I had a similar problem, I would just check for whether the image was loaded or not, and if not, set a timeout to call the function again, so it would keep trying until it was loaded. This would avoid any possible race condition.

Categories

Resources