Calculate image dimensions on screen size before rendering - javascript

Is there a way of calculating / estimating what the image size would be depending on the screen resolution before the image has been rendered? I need more logical help rather than code to be honest. What do I need to calculate?
Image size: 800px * 450px
Window size: 424px * 728px
The image works out to be 424px * 239px. I need to calculate this in code so I can adjust positions of other elements following after (absolute / fixed elements).
What I have done so far is;
var ratio1 = (this.retrievedNewsArticle.featuredImage.width / this.retrievedNewsArticle.featuredImage.height);
var ratio2 = ($(window).innerWidth() / this.retrievedNewsArticle.featuredImage.width);
// Ratio 1 = 424
// Ratio 2 = 0.53
So what's next?

It sounds like you already know the image's size, and it sounds like you want the image to be the full width of the window, and just need to know how to determine the height of the image. If so, the target height is the image height times the windows width divided by the image width:
var renderedWidth = imageWidth;
var renderedHeight = imageHeight * (windowWidth / imageWidth);
That maintains the aspect ratio.
That assumes the image is always wider than the screen. Let's remove that assumption.
If you want the image to stretch to fill:
var renderedWidth, renderedHeight;
if (windowWidth >= imageWidth) {
renderedWidth = imageWidth * (windowWidth / imageWidth);
} else {
renderedWidth = imageWidth;
}
renderedHeight = imageHeight * (windowWidth / renderedWidth);
If you don't want the image to stretch to fill:
var renderedWidth, renderedHeight;
if (windowWidth >= imageWidth) {
renderedWidth = imageWidth;
renderedHeight = imageHeight;
} else {
renderedWidth = imageWidth;
renderedHeight = imageHeight * (windowWidth / imageWidth);
}

Related

Keeping aspect ratio when height AND width both need to change

I am trying to make an image resize based on values given to it (width/height)
The values must not exceed the maxheight and maxwidth but must maintain ratio.
Right now it works if I make the height or width too big, but if both are triggered it doesn't work. So it's a logical error, can someone please help me with this.
if (maxwidth <= width || maxheight <= height) {
if(width > maxwidth) {
var newheight = height * (maxwidth/width);
newwidth = maxwidth;
console.log("new height");
}
if(height > maxheight) {
var newwidth = width * (maxheight/height);
newheight = maxheight;
console.log("new width");
}
For it in action go here: https://codepen.io/anon/pen/XBEvNO
The error occurs when say width is 1500 and height is 600.
I know it's because the second if statement overwrites the first, but I don't know how to fix this logic.
First off, if you do not want the values to exceed their maximums, but do want to scale the image so that it keeps the ratio, you need to set the size values to the maximum before you work out the resulting width/height from that change in width/height.
Second, if you want the ratio to be the same, then you should not be able to change both the height and the width at the same time, because if you change the width, there is exactly one other height value that maintains the ratio
The math for this would be like so:
R = Ratio (Assuming your max values are the ratio you want R = MaxWidth / MaxHeight)
H = Height
W = Width
W = H*R
H = W/R
if (maxwidth <= width) {
if(width > maxwidth) {
newwidth = maxwidth;
var newheight = newwidth / (maxwidth/maxheight);
console.log("new height");
}
Not only would this need to be changed so that the ratio is a proper ratio but the code you have for making it smaller would also need to be altered.
If by ratio you did not mean the ratio of the original images W/H, please clarify.
For maintaining the inputed user ratio try this:
if (maxwidth <= width || maxheight <= height) {
var ratio = width/height;
var heightRatio = height/maxheight;
var widthRatio = width/maxwidth
if(width > maxwidth && widthRatio >= heightRatio) {
newwidth = maxwidth;
var newheight = newwidth / ratio;
console.log("new height");
}
else if(height > maxheight && heightRatio > widthRatio) {
newheight = maxheight;
var newwidth = newheight * ratio;
console.log("new width");
}
Checking the larger of the sizes compared to their max size ensures that when the scaling happens, the size largest over the maximum size gets scaled to max, this way the other size does not still go over max at some times
You need to decide whether you will scale by the ratio of height/maxHeight or width/maxWidth then see which one you can use without making the other dimension too big. Another way of thinking is asking: if we maximize the width, does the height get too big? If not maximize the width, otherwise maximize the height. Either way, we scale by the same scale for width and height so the aspect ratio stays the same. (You would probably want to add sanity checks for divide by zero)
function resize(size, max){
// can we maximize the width without exceeding height limit?
let resize_factor = (size.height / ( size.width/max.width)) <= max.height
? size.width/max.width
: size.height/max.height
return {width: size.width/resize_factor, height: size.height/resize_factor}
}
let max = {
width: 100,
height: 50
}
console.log(resize({width: 500, height:50}, max))
console.log(resize({width: 500, height:1000}, max))
console.log(resize({width: 40, height:10}, max))
console.log(resize({width: 1, height:2}, max))
console.log(resize({width: 2, height:1}, max))

Scaling an image to best fit the viewport

Suppose I have a viewport of an arbitrary size (eg, a browser window). I want to scale an image of arbitrary aspect ratio and resolution to fit inside of this viewport in a way that maximizes the resolution.
I'm having difficulty getting the code to work for circumstances where the image is both too tall and too wide. What equation can I use to figure out if I should scale this arbitrary image by width or by height?
Here's the code that I'm using:
var aspectRatio = imageWidth / imageHeight;
if(tooWide && tooTall)
{
// Figure out if it's better to scale on height or width by
if((imageWidth - viewporthWidth) > (imageHeight - viewporthHeight))
{
adaptedWidth = (1.0 - padding) * viewporthWidth;
adaptedHeight = adaptedWidth / aspectRatio;
}
else
{
adaptedHeight = (1.0 - padding) * viewporthHeight;
adaptedWidth = adaptedHeight * aspectRatio;
}
}
else if(tooWide)
{
adaptedWidth = (1.0 - padding) * viewporthWidth;
adaptedHeight = adaptedWidth / aspectRatio;
}
else if(tooTall)
{
adaptedHeight = (1.0 - padding) * viewporthHeight;
adaptedWidth = adaptedHeight * aspectRatio;
}
else
{
adaptedWidth = imageWidth;
adaptedHeight = imageHeight;
}
I'm having some circumstance where images of a certain size are not being scaled at all. For example, a 3000 x 1997 image is being resized to 1342 x 893 when my viewport size is 1492 x 855. The aspect ratio is correct, but the height is wrong. This implies the condition of the nested if statement is wrong (and indeed, it evaluates to 1003 > 1104, which hints that we should be scaling by height.
I assume that this means that the equations used for scaling the image are insufficient.
Side note: this code is JavaScript that is being used to scale an image (using the browser's native scaling via the width and height attributes on the image element). In the code above, padding is a percentage to that creates a minimum amount of padding around the image (so it doesn't take up the entire viewport). I included this in the code because the default padding is 0.10, and that affects the numbers that I mentioned.
You should be comparing the ratios of image to viewport, not the absolute differences.
Something along these lines:
if((imageWidth / viewporthWidth) > (imageHeight / viewporthHeight))
This will essentially compare the percentage difference instead of absolute difference. This is important because when you scale the image, the image is reduced by a percentage, not by an absolute amount in both width and height.
EDIT:
You can see here, this is an example with your code:
http://jsfiddle.net/X2Yq6/1
And with the updated code:
http://jsfiddle.net/X2Yq6/
In this example, the absolute difference in width is larger, but the percentage difference in height is higher. The old code scaled based on width (incorrectly) and the new code scales on height.
My final answer:
var aspectRatio = imageWidth / imageHeight;
var viewportRatio = viewportWidth / viewportHeight;
var adaptedHeight = imageHeight;
var adaptedWidth = imageWidth;
if (viewportRatio > aspectRatio) // scale by width or height?
{ adaptedHeight *= viewportWidth / imageWidth;
adaptedWidth *= viewportWidth / imageWidth;
}
else
{ adaptedHeight *= viewportHeight / imageHeight;
adaptedWidth *= viewportHeight / imageHeight;
}

javascript for image resize is not working in IE?

The below given code resizes an image to 160x160 and works fine for Firefox & Chrome but not for Internet Explorer. Why?
$(document).ready(function() {
$('#imagePreview img').each(function() {
$('#imagePreview img').each(function() {
var maxWidth = 160; // Max width for the image
var maxHeight = 160; // Max height for the image
var ratio = 0; // Used for aspect ratio
var width = $(this).width(); // Current image width
var height = $(this).height(); // Current image height
// Check if the current width is larger than the max
if(width > maxWidth){
ratio = maxWidth / width;
$(this).css("width", maxWidth); // Set new width
$(this).css("height", height * ratio); // Scale height based on ratio
height = height * ratio; // Reset height to match scaled image
width = width * ratio; // Reset width to match scaled image
}
// Check if current height is larger than max
if(height > maxHeight){
ratio = maxHeight / height;
$(this).css("height", maxHeight); // Set new height
$(this).css("width", width * ratio); // Scale width based on ratio
width = width * ratio; // Reset width to match scaled image
}
});
});
});
You're not waiting for the images to be loaded, so they're not guaranteed to have a size (depending on whether they're cached).
You should replace
$(document).ready(function() {
with
$(document).load(function() {
This being said, it looks like you could replace the whole with this style :
#imagePreview img {
max-width: 160px;
max-height: 160px;
}
(see demonstration)

Min size with aspect ratio resize image

I'm doing a resize function over an image using this code:
$('.image_resize').each(function(){
var ww = $(window).width() - 80 - 400;
var wh = $(window).height() - 60;
var iar = $(this).attr('height') / $(this).attr('width');
var war = wh / ww;
if(iar <= war){
$(this).attr("width" , ww);
$(this).attr("height" , ww * iar);
}else{
$(this).attr("height" , wh);
$(this).attr("width" , wh / iar);
}
})
this markup:
<div id="home_image">
<img class="image_resize" src="img/home_image.jpg" alt="home_image" width="945" height="557">
</div>
The code works nice and resize the image with the correct aspect ratio, but the problem is that there is no minium limit to that resize, so the image can became as small as 20 pixel * ratio and I want to limit that.
How can limit the image to just say to a minium height of 400px and cropping the container over it, or any thing like that?
You can do it by simply checking if window height is less than 400. If it is then force it to be 400 using following code.
var wh = $(window).height() - 60;
wh = wh < 400 ? 400 : wh;
There are two things to consider here:
1) The size of the image is restricted by ww and wh. You may wish to specify a minimum width and height for the area the image.
var ww = $(window).width() - 80 - 400;
var wh = $(window).height() - 60;
ww= ww<50 ? 50 : ww;
wh= wh<50 ? 50 : wh;
2) The size of the image is also affected by it's aspect ratio. So lets say you have a panoramic image - above code will make sure that the minimum width is 50 pixels, but it's height might only be 15 px because of its aspect ratio. If you want to enforce a minimal height in those cases, you'll have to change the code withing your conditional blocks. Please note that this will also change the actual width to be much wider than ww limits it to.
if(iar <= war){
if (ww*iar<50) {
$(this).attr("width" , 50 / iar);
$(this).attr("height" , 50);
} else {
$(this).attr("width" , ww);
$(this).attr("height" , ww * iar);
}
}else{
if (wh*iar<50) {
$(this).attr("height" , 50 * iar);
$(this).attr("width" , 50);
} else {
$(this).attr("height" , wh);
$(this).attr("width" , wh / iar);
}
}

How to resize images proportionally / keeping the aspect ratio?

I have images that will be quite big in dimension and I want to shrink them down with jQuery while keeping the proportions constrained, i.e. the same aspect ratio.
Can someone point me to some code, or explain the logic?
I think this is a really cool method:
/**
* Conserve aspect ratio of the original region. Useful when shrinking/enlarging
* images to fit into a certain area.
*
* #param {Number} srcWidth width of source image
* #param {Number} srcHeight height of source image
* #param {Number} maxWidth maximum available width
* #param {Number} maxHeight maximum available height
* #return {Object} { width, height }
*/
function calculateAspectRatioFit(srcWidth, srcHeight, maxWidth, maxHeight) {
var ratio = Math.min(maxWidth / srcWidth, maxHeight / srcHeight);
return { width: srcWidth*ratio, height: srcHeight*ratio };
}
Have a look at this piece of code from http://ericjuden.com/2009/07/jquery-image-resize/
$(document).ready(function() {
$('.story-small img').each(function() {
var maxWidth = 100; // Max width for the image
var maxHeight = 100; // Max height for the image
var ratio = 0; // Used for aspect ratio
var width = $(this).width(); // Current image width
var height = $(this).height(); // Current image height
// Check if the current width is larger than the max
if(width > maxWidth){
ratio = maxWidth / width; // get ratio for scaling image
$(this).css("width", maxWidth); // Set new width
$(this).css("height", height * ratio); // Scale height based on ratio
height = height * ratio; // Reset height to match scaled image
width = width * ratio; // Reset width to match scaled image
}
// Check if current height is larger than max
if(height > maxHeight){
ratio = maxHeight / height; // get ratio for scaling image
$(this).css("height", maxHeight); // Set new height
$(this).css("width", width * ratio); // Scale width based on ratio
width = width * ratio; // Reset width to match scaled image
height = height * ratio; // Reset height to match scaled image
}
});
});
If I understand the question correctly, you don't even need jQuery for this. Shrinking the image proportionally on the client can be done with CSS alone: just set its max-width and max-height to 100%.
<div style="height: 100px">
<img src="http://www.getdigital.de/images/produkte/t4/t4_css_sucks2.jpg"
style="max-height: 100%; max-width: 100%">
</div>​
Here's the fiddle: http://jsfiddle.net/9EQ5c/
In order to determine the aspect ratio, you need to have a ratio to aim for.
function getHeight(length, ratio) {
var height = ((length)/(Math.sqrt((Math.pow(ratio, 2)+1))));
return Math.round(height);
}
function getWidth(length, ratio) {
var width = ((length)/(Math.sqrt((1)/(Math.pow(ratio, 2)+1))));
return Math.round(width);
}
In this example I use 16:10 since this the typical monitor aspect ratio.
var ratio = (16/10);
var height = getHeight(300,ratio);
var width = getWidth(height,ratio);
console.log(height);
console.log(width);
Results from above would be 147 and 300
There are 4 parameters to this problem
current image width iX
current image height iY
target viewport width cX
target viewport height cY
And there are 3 different conditional parameters
cX > cY ?
iX > cX ?
iY > cY ?
solution
Find the smaller side of the target view port F
Find the larger side of the current view port L
Find the factor of both F/L = factor
Multiply both sides of the current port with the factor ie, fX = iX * factor; fY = iY * factor
that's all you need to do.
//Pseudo code
iX;//current width of image in the client
iY;//current height of image in the client
cX;//configured width
cY;//configured height
fX;//final width
fY;//final height
1. check if iX,iY,cX,cY values are >0 and all values are not empty or not junk
2. lE = iX > iY ? iX: iY; //long edge
3. if ( cX < cY )
then
4. factor = cX/lE;
else
5. factor = cY/lE;
6. fX = iX * factor ; fY = iY * factor ;
This is a mature forum, I am not giving you code for that :)
actually i have just run into this problem and the solution I found was strangely simple and weird
$("#someimage").css({height:<some new height>})
and miraculously the image is resized to the new height and conserving the same ratio!
Does <img src="/path/to/pic.jpg" style="max-width:XXXpx; max-height:YYYpx;" > help?
Browser will take care of keeping aspect ratio intact.
i.e max-width kicks in when image width is greater than height and its height will be calculated proportionally. Similarly max-height will be in effect when height is greater than width.
You don't need any jQuery or javascript for this.
Supported by ie7+ and other browsers (http://caniuse.com/minmaxwh).
If the image is proportionate then this code will fill the wrapper with image. If image is not in proportion then extra width/height will get cropped.
<script type="text/javascript">
$(function(){
$('#slider img').each(function(){
var ReqWidth = 1000; // Max width for the image
var ReqHeight = 300; // Max height for the image
var width = $(this).width(); // Current image width
var height = $(this).height(); // Current image height
// Check if the current width is larger than the max
if (width > height && height < ReqHeight) {
$(this).css("min-height", ReqHeight); // Set new height
}
else
if (width > height && width < ReqWidth) {
$(this).css("min-width", ReqWidth); // Set new width
}
else
if (width > height && width > ReqWidth) {
$(this).css("max-width", ReqWidth); // Set new width
}
else
(height > width && width < ReqWidth)
{
$(this).css("min-width", ReqWidth); // Set new width
}
});
});
</script>
This should work for images with all possible proportions
$(document).ready(function() {
$('.list img').each(function() {
var maxWidth = 100;
var maxHeight = 100;
var width = $(this).width();
var height = $(this).height();
var ratioW = maxWidth / width; // Width ratio
var ratioH = maxHeight / height; // Height ratio
// If height ratio is bigger then we need to scale height
if(ratioH > ratioW){
$(this).css("width", maxWidth);
$(this).css("height", height * ratioW); // Scale height according to width ratio
}
else{ // otherwise we scale width
$(this).css("height", maxHeight);
$(this).css("width", height * ratioH); // according to height ratio
}
});
});
Here's a correction to Mehdiway's answer. The new width and/or height were not being set to the max value. A good test case is the following (1768 x 1075 pixels): http://spacecoastsports.com/wp-content/uploads/2014/06/sportsballs1.png. (I wasn't able to comment on it above due to lack of reputation points.)
// Make sure image doesn't exceed 100x100 pixels
// note: takes jQuery img object not HTML: so width is a function
// not a property.
function resize_image (image) {
var maxWidth = 100; // Max width for the image
var maxHeight = 100; // Max height for the image
var ratio = 0; // Used for aspect ratio
// Get current dimensions
var width = image.width()
var height = image.height();
console.log("dimensions: " + width + "x" + height);
// If the current width is larger than the max, scale height
// to ratio of max width to current and then set width to max.
if (width > maxWidth) {
console.log("Shrinking width (and scaling height)")
ratio = maxWidth / width;
height = height * ratio;
width = maxWidth;
image.css("width", width);
image.css("height", height);
console.log("new dimensions: " + width + "x" + height);
}
// If the current height is larger than the max, scale width
// to ratio of max height to current and then set height to max.
if (height > maxHeight) {
console.log("Shrinking height (and scaling width)")
ratio = maxHeight / height;
width = width * ratio;
height = maxHeight;
image.css("width", width);
image.css("height", height);
console.log("new dimensions: " + width + "x" + height);
}
}
$('#productThumb img').each(function() {
var maxWidth = 140; // Max width for the image
var maxHeight = 140; // Max height for the image
var ratio = 0; // Used for aspect ratio
var width = $(this).width(); // Current image width
var height = $(this).height(); // Current image height
// Check if the current width is larger than the max
if(width > height){
height = ( height / width ) * maxHeight;
} else if(height > width){
maxWidth = (width/height)* maxWidth;
}
$(this).css("width", maxWidth); // Set new width
$(this).css("height", maxHeight); // Scale height based on ratio
});
2 Steps:
Step 1) calculate the ratio of the original width / original height of Image.
Step 2) multiply the original_width/original_height ratio by the new desired height to get the new width corresponding to the new height.
Without additional temp-vars or brackets.
var width= $(this).width(), height= $(this).height()
, maxWidth=100, maxHeight= 100;
if(width > maxWidth){
height = Math.floor( maxWidth * height / width );
width = maxWidth
}
if(height > maxHeight){
width = Math.floor( maxHeight * width / height );
height = maxHeight;
}
Keep in Mind: Search engines don't like it, if width and height attribute does not fit the image, but they don't know JS.
After some trial and error I came to this solution:
function center(img) {
var div = img.parentNode;
var divW = parseInt(div.style.width);
var divH = parseInt(div.style.height);
var srcW = img.width;
var srcH = img.height;
var ratio = Math.min(divW/srcW, divH/srcH);
var newW = img.width * ratio;
var newH = img.height * ratio;
img.style.width = newW + "px";
img.style.height = newH + "px";
img.style.marginTop = (divH-newH)/2 + "px";
img.style.marginLeft = (divW-newW)/2 + "px";
}
The resize can be achieved(maintaining aspect ratio) using CSS.
This is a further simplified answer inspired by Dan Dascalescu's post.
http://jsbin.com/viqare
img{
max-width:200px;
/*Or define max-height*/
}
<img src="http://e1.365dm.com/13/07/4-3/20/alastair-cook-ashes-profile_2967773.jpg" alt="Alastair Cook" />
<img src="http://e1.365dm.com/13/07/4-3/20/usman-khawaja-australia-profile_2974601.jpg" alt="Usman Khawaja"/>
This issue can be solved by CSS.
.image{
max-width:*px;
}
Resize to fit the container, get scale factor, scale down percentage control
$(function () {
let ParentHeight = 200;
let ParentWidth = 300;
$("#Parent").width(ParentWidth).height(ParentHeight);
$("#ParentHeight").html(ParentHeight);
$("#ParentWidth").html(ParentWidth);
var RatioOfParent = ParentHeight / ParentWidth;
$("#ParentAspectRatio").html(RatioOfParent);
let ChildHeight = 2000;
let ChildWidth = 4000;
var RatioOfChild = ChildHeight / ChildWidth;
$("#ChildAspectRatio").html(RatioOfChild);
let ScaleHeight = ParentHeight / ChildHeight;
let ScaleWidth = ParentWidth / ChildWidth;
let Scale = Math.min(ScaleHeight, ScaleWidth);
$("#ScaleFactor").html(Scale);
// old scale
//ChildHeight = ChildHeight * Scale;
//ChildWidth = ChildWidth * Scale;
// reduce scale by 10%, you can change the percentage
let ScaleDownPercentage = 10;
let CalculatedScaleValue = Scale * (ScaleDownPercentage / 100);
$("#CalculatedScaleValue").html(CalculatedScaleValue);
// new scale
let NewScale = (Scale - CalculatedScaleValue);
ChildHeight = ChildHeight * NewScale;
ChildWidth = ChildWidth * NewScale;
$("#Child").width(ChildWidth).height(ChildHeight);
$("#ChildHeight").html(ChildHeight);
$("#ChildWidth").html(ChildWidth);
});
#Parent {
background-color: grey;
}
#Child {
background-color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="Parent">
<div id="Child"></div>
</div>
<table>
<tr>
<td>Parent Aspect Ratio</td>
<td id="ParentAspectRatio"></td>
</tr>
<tr>
<td>Child Aspect Ratio</td>
<td id="ChildAspectRatio"></td>
</tr>
<tr>
<td>Scale Factor</td>
<td id="ScaleFactor"></td>
</tr>
<tr>
<td>Calculated Scale Value</td>
<td id="CalculatedScaleValue"></td>
</tr>
<tr>
<td>Parent Height</td>
<td id="ParentHeight"></td>
</tr>
<tr>
<td>Parent Width</td>
<td id="ParentWidth"></td>
</tr>
<tr>
<td>Child Height</td>
<td id="ChildHeight"></td>
</tr>
<tr>
<td>Child Width</td>
<td id="ChildWidth"></td>
</tr>
</table>
Resizing an image to a certain percentage
// scale can be 0.40, 0.80, etc.
function imageScaler(originalHeight, originalWidth, scale) {
const scaledWidth = originalWidth * scale;
const scaledHeight = (originalHeight / originalWidth) * scaledWidth;
return [scaledHeight, scaledWidth];
}
You can determine width height if you want a particular aspect ratio to do so,
Let you have a picture of 3264×2448
Pictures aspect ratio is => 2448 ÷ 3264 =0.75
Now just check number which gives 0.75 on division.
Like: for
16:9 => 9÷16 =0.5625 (wrong it is not 0.75)
Now 4:3 =>3÷4=0.75 (we get it )
So the original aspect ratio is 4:3
now to resize the image just do
Width=3264 ÷/× 4
Height=2448 ÷/× 3
÷ for reducing
× for increasing
Hope you can understand and code yourself this is very effective because we just need to do very basic arithmetic just division or multiplication so simple.
Let me know if i am wrong.
This totally worked for me for a draggable item - aspectRatio:true
.appendTo(divwrapper).resizable({
aspectRatio: true,
handles: 'se',
stop: resizestop
})

Categories

Resources