Getting original image for cropping, ignoring the width attribute? - javascript

My user can upload really big images, and for cropping and display purposes i'm adding width attribute so it will fit well in the browser window. Real image size can be - say 1920 x 1080 px.
<!-- width added for display purpose -->
<img class="croppable" src="images/fhd.jpg" width="640" />
In order to calculate real selection box dimension (if the x coordinate is 20px then would be 60px in the original full hd picture) i need to get the full image size before apply the width attribute.
The problem is that this will return 640 as value, taking into account the width attribute:
// Important: Use load event to avoid problems with webkit browser like safari
// when using cached images
$(window).load(function(){
$('img.croppable').each(function(){
alert(this.width);
});
});
Please don't flag this as duplicate since what i'm asking is completly different from simple image width/height retrival (which works, actually).
EDIT: Chris G. solution seems not working:
$(window).load(function(){
$('img.croppable').each(function(){
console.log(this.src);
var original = new Image(this.src);
console.log(original);
$("#original_w").text(original.width); // Temp, more images to be added
$("#original_h").text(original.height); // Temp, more images to be added
});
});
Console output:
http://localhost/DigitLifeAdminExtension/images/pillars-of-creation.jpg
<img width="0">

Get the width/height of the image itself, not the div it is contained within.
$(window).load(function(){
$('img.croppable').each(function(){
var img = new Image();
img.src = $(this).src;
alert(img.width);
});
});

You can remove the attributes, get the width and put the attributes in place again:
var $img = $(img);
var oldWidth = $img.attr("width");
var imgWidth = $img.removeAttr("width").width();
$img.width(oldWidth);
But I think Chris G.'s answer works well too, just making sure it will be loaded when you try to get the width:
img.onload = function() {
if (!img.complete) return; // IMG not loaded
width = img.width;
imgManipulationGoesHere();
}

Works in most up-to-date browsers and IE9.
$(window).load(function(){
$('img.croppable').each(function(){
alert(this.naturalHeight);
});
});

The working solution would be:
$(function(){
$('img.croppable').each(function () {
var original = new Image(this.src);
original.onload = function () {
alert(original.src + ': ' + original.width + 'x' +original.height);
};
});
});

Related

Get image size already on DOM with jquery / javascript [duplicate]

Is there a JavaScript or jQuery API or method to get the dimensions of an image on the page?
You can programmatically get the image and check the dimensions using JavaScript...
const img = new Image();
img.onload = function() {
alert(this.width + 'x' + this.height);
}
img.src = 'http://www.google.com/intl/en_ALL/images/logo.gif';
This can be useful if the image is not a part of the markup.
clientWidth and clientHeight are DOM properties that show the current in-browser size of the inner dimensions of a DOM element (excluding margin and border). So in the case of an IMG element, this will get the actual dimensions of the visible image.
var img = document.getElementById('imageid');
//or however you get a handle to the IMG
var width = img.clientWidth;
var height = img.clientHeight;
Also (in addition to Rex and Ian's answers) there is:
imageElement.naturalHeight
and
imageElement.naturalWidth
These provide the height and width of the image file itself (rather than just the image element).
If you are using jQuery and you are requesting image sizes you have to wait until they load or you will only get zeroes.
$(document).ready(function() {
$("img").load(function() {
alert($(this).height());
alert($(this).width());
});
});
Using clientWidth and clientHeight is, I think, now obsolete.
I have done some experiments with HTML5, to see which values actually get returned.
First of all, I used a program called Dash to get an overview of the image API.
It states that height and width are the rendered height/width of the image and that naturalHeight and naturalWidth are the intrinsic height/width of the image (and are HTML5 only).
I used an image of a beautiful butterfly, from a file with height 300 and width 400. And this JavaScript code:
var img = document.getElementById("img1");
console.log(img.height, img.width);
console.log(img.naturalHeight, img.naturalWidth);
console.log($("#img1").height(), $("#img1").width());
Then I used this HTML, with inline CSS for the height and width.
<img style="height:120px;width:150px;" id="img1" src="img/Butterfly.jpg" />
Results:
/* Image element */ height == 300 width == 400
naturalHeight == 300 naturalWidth == 400
/* jQuery */ height() == 120 width() == 150
/* Actual rendered size */ 120 150
I then changed the HTML to the following:
<img height="90" width="115" id="img1" src="img/Butterfly.jpg" />
I.e., using height and width attributes rather than inline styles.
Results:
/* Image element */ height == 90 width == 115
naturalHeight == 300 naturalWidth == 400
/* jQuery */ height() == 90 width() == 115
/* Actual rendered size */ 90 115
I then changed the HTML to the following:
<img height="90" width="115" style="height:120px;width:150px;" id="img1" src="img/Butterfly.jpg" />
I.e., using both attributes and CSS, to see which takes precedence.
Results:
/* Image element */ height == 90 width == 115
naturalHeight == 300 naturalWidth == 400
/* jQuery */ height() == 120 width() == 150
/* Actual rendered size */ 120 150
Using jQuery, you do this:
var imgWidth = $("#imgIDWhatever").width();
The thing all other have forgot is that you can’t check image size before it loads. When the author checks all of posted methods it will work probably only on localhost.
Since jQuery could be used here, remember that the 'ready' event is fired before images are loaded. $('#xxx').width() and .height() should be fired in the onload event or later.
You can only really do this using a callback of the load event as the size of the image is not known until it has actually finished loading. Something like the code below...
var imgTesting = new Image();
function CreateDelegate(contextObject, delegateMethod)
{
return function()
{
return delegateMethod.apply(contextObject, arguments);
}
}
function imgTesting_onload()
{
alert(this.width + " by " + this.height);
}
imgTesting.onload = CreateDelegate(imgTesting, imgTesting_onload);
imgTesting.src = 'yourimage.jpg';
Let's combine everything we learned here into one simple function (imageDimensions()). It uses promises.
// helper to get dimensions of an image
const imageDimensions = file =>
new Promise((resolve, reject) => {
const img = new Image()
// the following handler will fire after a successful loading of the image
img.onload = () => {
const { naturalWidth: width, naturalHeight: height } = img
resolve({ width, height })
}
// and this handler will fire if there was an error with the image (like if it's not really an image or a corrupted one)
img.onerror = () => {
reject('There was some problem with the image.')
}
img.src = URL.createObjectURL(file)
})
// here's how to use the helper
const getInfo = async ({ target: { files } }) => {
const [file] = files
try {
const dimensions = await imageDimensions(file)
console.info(dimensions)
} catch(error) {
console.error(error)
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/7.0.0-beta.3/babel.min.js"></script>
Select an image:
<input
type="file"
onchange="getInfo(event)"
/>
<br />
<small>It works offline.</small>
To get the natural height and width:
document.querySelector("img").naturalHeight;
document.querySelector("img").naturalWidth;
<img src="img.png">
And if you want to get style height and width:
document.querySelector("img").offsetHeight;
document.querySelector("img").offsetWidth;
Assuming, we want to get image dimensions of <img id="an-img" src"...">
// Query after all the elements on the page have loaded.
// Or, use `onload` on a particular element to check if it is loaded.
document.addEventListener('DOMContentLoaded', function () {
var el = document.getElementById("an-img");
console.log({
"naturalWidth": el.naturalWidth, // Only on HTMLImageElement
"naturalHeight": el.naturalHeight, // Only on HTMLImageElement
"offsetWidth": el.offsetWidth,
"offsetHeight": el.offsetHeight
});
})
Natural Dimensions
el.naturalWidth and el.naturalHeight will get us the natural dimensions, the dimensions of the image file.
Layout Dimensions
el.offsetWidth and el.offsetHeight will get us the dimensions at which the element is rendered on the document.
This answer was exactly what I was looking for (in jQuery):
var imageNaturalWidth = $('image-selector').prop('naturalWidth');
var imageNaturalHeight = $('image-selector').prop('naturalHeight');
I think I improved the source code to be able to let the image load before trying to find out its properties. Otherwise, it will display '0 * 0', because the next statement would have been called before the file was loaded into the browser. It requires jQuery...
function getImgSize(imgSrc) {
var newImg = new Image();
newImg.src = imgSrc;
var height = newImg.height;
var width = newImg.width;
p = $(newImg).ready(function() {
return {width: newImg.width, height: newImg.height};
});
alert (p[0]['width'] + " " + p[0]['height']);
}
I thought this might be helpful to some who are using JavaScript and/or TypeScript in 2019.
I found the following, as some have suggested, to be incorrect:
let img = new Image();
img.onload = function() {
console.log(this.width, this.height) // Error: undefined is not an object
};
img.src = "http://example.com/myimage.jpg";
This is correct:
let img = new Image();
img.onload = function() {
console.log(img.width, img.height)
};
img.src = "http://example.com/myimage.jpg";
Conclusion:
Use img, not this, in the onload function.
With the jQuery library-
Use .width() and .height().
More in jQuery width and jQuery heigth.
Example Code-
$(document).ready(function(){
$("button").click(function()
{
alert("Width of image: " + $("#img_exmpl").width());
alert("Height of image: " + $("#img_exmpl").height());
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
<img id="img_exmpl" src="http://images.all-free-download.com/images/graphicthumb/beauty_of_nature_9_210287.jpg">
<button>Display dimensions of img</button>
Before using the real image size, you should load the source image. If you use the jQuery framework, you can get the real image size in a simple way.
$("ImageID").load(function(){
console.log($(this).width() + "x" + $(this).height())
})
A jQuery answer:
$height = $('#image_id').height();
$width = $('#image_id').width();
My two cents in jQuery
Disclaimer: This does not necessarily answer this question, but broadens our capabilities. It was tested and working in jQuery 3.3.1
Let’s consider:
You have the image URL/path and you want to get the image width and height without rendering it on the DOM,
Before rendering image on the DOM, you need to set the offsetParent node or image div wrapper element to the image width and height, to create a fluid wrapper for different image sizes, i.e., when clicking a button to view image on a modal/lightbox
This is how I will do it:
// image path
const imageUrl = '/path/to/your/image.jpg'
// Create dummy image to get real width and height
$('<img alt="" src="">').attr("src", imageUrl).on('load', function(){
const realWidth = this.width;
const realHeight = this.height;
alert(`Original width: ${realWidth}, Original height: ${realHeight}`);
})
Recently I had the same issue for an error in the flex slider. The first image's height was set smaller due to the loading delay. I tried the following method for resolving that issue and it's worked.
// Create an image with a reference id. Id shall
// be used for removing it from the DOM later.
var tempImg = $('<img id="testImage" />');
// If you want to get the height with respect to any specific width you set.
// I used window width here.
tempImg.css('width', window.innerWidth);
tempImg[0].onload = function () {
$(this).css('height', 'auto').css('display', 'none');
var imgHeight = $(this).height();
// Remove it if you don't want this image anymore.
$('#testImage').remove();
}
// Append to body
$('body').append(tempImg);
// Set an image URL. I am using an image which I got from Google.
tempImg[0].src ='http://aspo.org/wp-content/uploads/strips.jpg';
This will give you the height with respect to the width you set rather than original width or Zero.
Nicky De Maeyer asked for a background picture; I simply get it from the CSS content and replace the "url()":
var div = $('#my-bg-div');
var url = div.css('background-image').replace(/^url\(\'?(.*)\'?\)$/, '$1');
var img = new Image();
img.src = url;
console.log('img:', img.width + 'x' + img.height); // Zero, image not yet loaded
console.log('div:', div.width() + 'x' + div.height());
img.onload = function() {
console.log('img:', img.width + 'x' + img.height, (img.width/div.width()));
}
You can apply the onload handler property when the page loads in JavaScript or jQuery like this:
$(document).ready(function(){
var width = img.clientWidth;
var height = img.clientHeight;
});
This is an alternative answer for Node.js. That isn't likely what the OP meant, but it could come in handy and seems to be in the scope of the question.
This is a solution with Node.js, and the example uses the Next.js framework, but it would work with any Node.js framework. It uses the probe-image-size NPM package to resolve the image attributes from the server side.
Example use case: I used the below code to resolve the size of an image from an Airtable Automation script, which calls my own analyzeImage API and returns the image's props.
import {
NextApiRequest,
NextApiResponse,
} from 'next';
import probe from 'probe-image-size';
export const analyzeImage = async (req: NextApiRequest, res: NextApiResponse): Promise<void> => {
try {
const result = await probe('http://www.google.com/intl/en_ALL/images/logo.gif');
res.json(result);
} catch (e) {
res.json({
error: true,
message: process.env.NODE_ENV === 'production' ? undefined : e.message,
});
}
};
export default analyzeImage;
Yields:
{
"width": 276,
"height": 110,
"type": "gif",
"mime": "image/gif",
"wUnits": "px",
"hUnits": "px",
"length": 8558,
"url": "http://www.google.com/intl/en_ALL/images/logo.gif"
}
In my case, I have a File type (that is guaranteed to be an image), and I want the image dimensions without loading it on the DOM.
General strategy: Convert File to ArrayBuffer → Convert ArrayBuffer to a base64 string → use this as the image source with an Image class → use naturalHeight & naturalWidth to get dimensions.
const fr = new FileReader();
fr.readAsArrayBuffer(image); // Image the 'File' object
fr.onload = () => {
const arrayBuffer: ArrayBuffer = fr.result as ArrayBuffer;
// Convert to base64. String.fromCharCode can hit a stack overflow error if you pass
// the entire arrayBuffer in, and iteration gets around this
let binary = '';
const bytes = new Uint8Array(arrayBuffer);
bytes.forEach(b => binary += String.fromCharCode(b));
const base64Data = window.btoa(binary);
// Create an image object. Note, a default width/height MUST be given to the constructor (per
// the documentation) or naturalWidth/Height will always return 0.
const imageObj = new Image(100, 100);
imageObj.src = `data:${image.type};base64,${base64Data}`;
imageObj.onload = () => {
console.log(imageObj.naturalWidth, imageObj.naturalHeight);
}
}
This allows you to get the image dimensions and aspect ratio all from a File without rendering it. It can easily convert the onload functions to RxJS Observables using fromEvent for a better async experience:
// fr is the file reader, and this is the same as fr.onload = () => { ... }
fromEvent(fr, 'load')
Simply, you can test like this.
<script>
(function($) {
$(document).ready(function() {
console.log("ready....");
var i = 0;
var img;
for(i=1; i<13; i++) {
img = new Image();
img.src = 'img/' + i + '.jpg';
console.log("name : " + img.src);
img.onload = function() {
if(this.height > this.width) {
console.log(this.src + " : portrait");
}
else if(this.width > this.height) {
console.log(this.src + " : landscape");
}
else {
console.log(this.src + " : square");
}
}
}
});
}(jQuery));
</script>
const file = event.target.files[0];
const img = new Image();
img.onload = function () {
width = img.width;
height = img.height;
};
img.src = URL.createObjectURL(file);
alert(width + "x" + height);
It is important to remove the browser interpreted setting from the parent div. So if you want the real image width and height, you can just use
$('.right-sidebar').find('img').each(function(){
$(this).removeAttr("width");
$(this).removeAttr("height");
$(this).imageResize();
});
This is one TYPO3 project example from me where I need the real properties of the image to scale it with the right relation.
Use
function outmeInside() {
var output = document.getElementById('preview_product_image');
if (this.height < 600 || this.width < 600) {
output.src = "http://localhost/danieladenew/uploads/no-photo.jpg";
alert("The image you have selected is low resolution image. Your image width=" + this.width + ", height=" + this.height + ". Please select image greater or equal to 600x600. Thanks!");
}
else {
output.src = URL.createObjectURL(event.target.files[0]);
}
return;
}
img.src = URL.createObjectURL(event.target.files[0]);
}
This works for multiple images preview and upload. If you have to select for each of the images one by one, then copy and paste into all the preview image function and validate!!!
Before acquiring an element's attributes, the document page should be onload:
window.onload = function(){
console.log(img.offsetWidth,img.offsetHeight);
}
Just pass the 'img' file object which is obtained by the input element. When we select the correct file, it will give the netural height and width of the image.
function getNeturalHeightWidth(file) {
let h, w;
let reader = new FileReader();
reader.onload = () => {
let tmpImgNode = document.createElement("img");
tmpImgNode.onload = function() {
h = this.naturalHeight;
w = this.naturalWidth;
};
tmpImgNode.src = reader.result;
};
reader.readAsDataURL(file);
}
return h, w;
}
You can also use:
var image=document.getElementById("imageID");
var width=image.offsetWidth;
var height=image.offsetHeight;

JQuery: How to hide an image until source changed

I have an image that is being resized programmatically, based on the current height/width of the container. My problem is that it shows the image at it's original size before it does the resizing.
See this JSFiddle
You'll notice how it flashes up a stretched image before it fits the image nicely in the middle.
I want to hide the image until that resizing has taken place, but I can't figure out how.
Any suggestions?
JSCode:
function LoadImg(img) {
img.css('visibility','hidden');
var src=img.attr('src');
var imgh = img.parent().height();
var imgw = img.parent().width();
var pattern = /&?(w|h)=[^&]+/g;
src = src.replace(pattern, '');
img.attr('src', src + '&w=' + imgw + '&h=' + imgh);
img.css('visibility','');
}
Html:
<div class="window">
<img src="http://www.angclassiccarparts.co.uk/image_anysize.aspx?f=/images/ww/panel/service_kits.jpg&w=154&h=154&color=png" id="img" onload="LoadImg($(this));" />
</div>
I've tried hiding with visibility hidden until the function has run, but that doesn't wait for it to load...
You're changing the source of the image, which forces it to load a new image, then you instantly set the image to visible.
Ultimately you want to wait until the second image is loaded before showing it, which can be achieved using .load() like so:
img.on('load', function() {
img.css('visibility','visible');
});
Here's an updated jsFiddle with the working code: http://jsfiddle.net/ev4YL/2/
I would, however, recommend a different approach. It doesn't make much sense to load an image, then when it's loaded load another image. Perhaps you should store the dimensions in html data attributes, then load the images dynamically on document.ready.
Something like this could work, if you set each image to have a data-src instead of src to begin with:
$('img').each(function() {
var img = $(this);
var src = img.attr('data-src');
var imgh = img.parent().height();
var imgw = img.parent().width();
var pattern = /&?(w|h)=[^&]+/g;
src = src.replace(pattern, '');
img.attr('src', src + '&w=' + imgw + '&h=' + imgh);
img.on('load', function() {
img.css('visibility','visible');
});
});
And the demo here: http://jsfiddle.net/ev4YL/4/
You can hide the image with display: none until the end of the function, then set the image to display: block (or whatever you need) at the very end. That way the rest of the function has already run, when it displays it will have already been resized.
See JSFiddle
But basically just:
CSS:
img {
display: none;
}
JavaScript:
function loadImg(img) {
----all of your function here----
img.css('display', 'block');
}

Get full size of image in javascript/jquery

I have an image on page that has been resized to fit in a div, say, 400x300. How can I get the full size of the image (~4000x3000) in jQuery? .width() and .height() only seem to return the current size of the image.
Images have naturalWidth and naturalHeight properties that contain the actual, non-modified width and height of the image, i.e. the real dimensions of the image, not what CSS sets it to.
One would still have to wait for the image to load though
$('#idOfMyimg').on('load', function() {
var height = this.naturalHeight,
width = this.naturalWidth;
});
Another option would be to create a new image with the same file as the source, and get the dimensions from that, as long as it's never added to the DOM, not external styles will affect it
var img = new Image();
img.onload = function() {
var height = this.height,
width = this.width;
}
img.src = $('#idOfMyimg').attr('src');
FIDDLE
You can clone the image, remove the height and width attributes, append it to the body and get the width and size before removing it.
jsFiddle demo is here: http://jsfiddle.net/58dA2/
Code is:
$(function() {
var img = $('#kitteh'); // image selector
var hiddenImg = img.clone().css('visibility', 'hidden').removeAttr('height').removeAttr('width').appendTo('body');
$('#height').text(hiddenImg.height());
$('#width').text(hiddenImg.width());
hiddenImg.remove();
});​
You can do this with an Image object that holds the same source file like:
var preloader = new Image();
preloader.src = 'path/to/my/file.jpg';
preloader.onload = function(){
var height = preloader.height;
var width = preloader.width;
}
Try this:
var pic = $("img")
// need to remove these in of case img-element has set width and height
pic.removeAttr("width");
pic.removeAttr("height");
var pic_real_width = pic.width();
var pic_real_height = pic.height();

Get image dimensions with Javascript before image has fully loaded

I've read about various kinds of ways getting image dimensions once an image has fully loaded, but would it be possible to get the dimensions of any image once it just started to load?
I haven't found much about this by searching (which makes me believe it's not possible), but the fact that a browser (in my case Firefox) shows the dimensions of any image I open up in a new tab right in the title after it just started loading the image gives me hope that there actually is a way and I just missed the right keywords to find it.
You are right that one can get image dimensions before it's fully loaded.
Here's a solution (demo):
var img = document.createElement('img');
img.src = 'some-image.jpg';
var poll = setInterval(function () {
if (img.naturalWidth) {
clearInterval(poll);
console.log(img.naturalWidth, img.naturalHeight);
}
}, 10);
img.onload = function () { console.log('Fully loaded'); }
The following code returns width/height as soon as it's available. For testing change abc123 in image source to any random string to prevent caching.
There is a JSFiddle Demo as well.
<div id="info"></div>
<img id="image" src="https://upload.wikimedia.org/wikipedia/commons/d/da/Island_Archway,_Great_Ocean_Rd,_Victoria,_Australia_-_Nov_08.jpg?abc123">
<script>
getImageSize($('#image'), function(width, height) {
$('#info').text(width + ',' + height);
});
function getImageSize(img, callback) {
var $img = $(img);
var wait = setInterval(function() {
var w = $img[0].naturalWidth,
h = $img[0].naturalHeight;
if (w && h) {
clearInterval(wait);
callback.apply(this, [w, h]);
}
}, 30);
}
</script>
One way is to use the HEAD request, which asks for HTTP Header of the response only. I know in HEAD responses, the size of the body is included. But I don't know if there anything available for size of images.

How can I change an image with another keeping aspect ratio?

I have the following HTML code:
<img id="Card00" src="images/words/back.png" onclick="imageClicked(0,0);">
And the following Javascript code:
function ShowImage(id, row, column)
{
var imagePath = 'images/words/' + id + '.png';
var imgId = '#Card' + row + '' + column;
$(imgId).attr('src', imagePath);
var width = $(imgId).attr('width');
var height = $(imgId).attr('height');
if (width > height)
$(imgId).attr('width', 200);
else
$(imgId).attr('height', 200);
}
imageClicked only calls ShowImage.
Back.png is 200x200. I want to change back.png image with another one. That another one (id + .png), is bigger than 200x200, so I need to resize it on ShowImage function.
But I can't do that, because I can't get its new width and height in this piece of code:
var width = $(imgId).attr('width');
var height = $(imgId).attr('height');
My goal is to change back.png image with another one, keeping aspect radio.
And there is another problem: first I see the bigger image, and then, sometimes, it gets 200x200. I said sometimes because sometimes I get its width or its height.
Any advice?
The best thing to do is just load the image into memory first, then once it loads get its real height and width, use that info -- URL, height and width -- to determine the appropriate dimensions. Note that this isn't foolproof, though, as caching can mess it up.
Note that you can generalize the below to include maximum dimensions in the function itself, but I think it's pretty easily adaptable:
// Example: replaceImage($("img#someID"), "http://example.com/logo.png");
var MAX_HEIGHT = 80;
var MAX_WIDTH = 80;
function keepAspectRatio(temp, $target, url) {
// Get height and width once loaded
var realHeight = temp.height;
var realWidth = temp.width;
// Get how much to divide by (1 if image fits in dimensions)
// Get rid of ", 1" if you just want everything to be either
// MAX_HEIGHT tall or MAX_WIDTH wide
var factor = Math.max(realHeight/MAX_HEIGHT, realWidth/MAX_WIDTH, 1);
realHeight /= factor;
realWidth /= factor;
// Set the target image's source, height and width
$target.attr("src", url).css({height: realHeight, width: realWidth});
}
function replaceImage($target, url) {
$("<img>").load(function() {
keepAspectRatio(this, $target, url);
}).attr("src", url);
}
jsFiddle Example
EDIT
Swapped places of attr and load per the comment below. I'm not going to go too crazy with optimization beyond that, as what we'd really do if we wanted things perfect would be to preload everything, get its real dimensions, and use that information each time we change the original image.
Did you try:
var width = $(imgId).clientWidth;
var height = $(imgId).clientHeight;

Categories