-2

I previously posted a similar question but I don't think I illustrated it very clearly.

If I have a basic responsive image such as <img src="http://www.example.com/nicephoto.jpg">

Let's say that nicephoto.jpg is a large image (4000x5000px). I could load the whole image and let it scale or be cropped by the browser as per its own css or the css of its container - but ideally I would like to ask the server to send me a crop of the image that already fits exactly the size I need. EDIT: My question is not how to do the server side cropping - I've got that covered. My question is as follows:

How can I find out what the maximum width and height of the image is until some of the image will be either cut off or the image will be scaled down? In other words, what is the largest practical size that this image should be?

I could always load a massive grey 10000x10000px placeholder image and then use jQuery's .width() and .height() to figure out how much space it actually takes up, but that is hardly efficient or ideal. Is there some smarter way to do this?

Thanks!

EDIT: I do not have control over what methods will be employed to restrict the maximum height or width of a given image. This code will be running on different sites. One site may use css max-height on the image itself. Another may have a set height for a container. I don't know. Either way I need to figure out how big an image can be shown before it begins to be scaled or cropped.

abagshaw
  • 6,162
  • 4
  • 38
  • 76
  • 5
    How would you define the 'maximum' image size? Is it determined by the container? The viewport? Something else? Where's your HTML, and in what part(s) should the image(s) be loaded? If you want this to be cropped at the server, what server-side scripting language are you using, [tag:PHP], [tag:Ruby], [tag:.Net], [tag:Node.js] or something else entirely? – David Thomas Aug 22 '16 at 17:38
  • Get the container width and multiply it by the aspect ratio to get the height. Use something like imagemagick to crop server side. – dlock Aug 22 '16 at 17:41
  • I have the server-side cropping covered. All I am trying to do is get a number value for max size and max width of the image. @DavidThomas, I'm not exactly sure what determines it (viewport, container, something else). It could be anything. What I am saying though is if I load a massive image and then use jquery .width() and .height() I get the information I need (how much space it could actually occupy) - but that isn't practical. I don't want to have to load a massive image. – abagshaw Aug 22 '16 at 17:54
  • There is no standard for _maximum_ image size @ websites? It's something **you** have to define. It's impossible for us to help finding the _maximum_ image size if you can't even answer how it should be determined. Flagged unclear. – fzzle Aug 22 '16 at 18:11
  • It's odd - this really doesn't seem as complicated or ambiguous to me at you seem to be making it. The point is this code needs to be able to run on different sites where different methods will be employed to restrict the max size of an image. That's why I don't know exactly what will be setting the max size of a given image. If your answer is - **there is no way to do this - as far as I know** that's allright, you can just say that. I think my question is pretty clear though :) – abagshaw Aug 22 '16 at 18:21

4 Answers4

2

Setting the late update aside for the moment:

It looks like you want to rescale an image on the server to the exact size needed by the client, rather than using CSS to resize the image in-browser. (Note that "crop" and "rescale" are different things; I'm assuming you actually mean "rescale".)

Here's one way to do what you're trying to do:

You do need, ultimately, to check the container's width and height on the client side -- the container size can't be known until page load, as it depends on the user's viewport size.

You can simplify communication with the server by using the image URL itself as a signal for the desired image to be generated. In this example I construct image URLs for placehold.it; you would instead substitute your own serverside script which would catch the url request, extract the desired width and height from the filename, and return the scaled image.

var reloadImage = function() {
  var w = $('.container').width();
  var h = $('.container').height();
  $('.container img').attr("src", "http://placehold.it/"+w+"x"+h);
  };
$('.container').mouseup(reloadImage);
.container {
  width: 100px; height: 100px;
  border: 2px solid;
  resize: both; /* Note that not all browser support "resize"; it's just for demo here, not essential to the technique itself */
  display: inline-block;
  overflow:auto
}

.container img {width: 100%;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Resize this container:<br>
<div class="container"><img class="image" src="http://placehold.it/100x100"></div>

(Note that there is no need to create a "massive" placeholder image as you suggest -- a single pixel image, CSS scaled to 100% width and height, will do. As will no placeholder image at all, of course.)

Here's why you should not do what you're trying to do:

  • It will defeat browser-side cacheing of the image (since different images may be needed on each load), effectively increasing bandwidth use rather than saving it.
  • The time spent serverside re-scaling the image will cost more than would have been saved compared to downloading a larger-than-necessary image (or, alternatively, you'd have to cache many different-sized variations on the image serverside to be handed out as needed.)
  • Resizing the window after load either triggers new image generation (wasting bandwidth and server time) or leads to potentially undersized images. Upscaled too-small images look significantly worse than downscaled too-large ones.

Here's what you should do instead

Create three or four different sized images each somewhat larger than a typical use case (think desktop, tablet, mobile) and use @media queries to choose one based on the screen size. Use in-browser scaling to tweak that selected image to the exact desired size.

.foo {  
  background:url('foo_default.png') no-repeat 50% 50% fixed;
  background-size: cover;
} 
@media only screen and (max-width: 400px) {
    .foo { background-image: url('foo_small.png'); }
}
@media only screen and (max-width: 800px) {
    .foo { background-image: url('foo_med.png'); }
}
@media only screen and (min-width: 800px) {
    .foo { background-image: url('foo_large.png'); }
}

But wait, there's an update

I do not have control over what methods will be employed to restrict the maximum height or width of a given image. This code will be running on different sites. One site may use css max-height on the image itself. Another may have a set height for a container. I don't know. Either way I need to figure out how big an image can be shown before it begins to be scaled or cropped.

This complicates things quite a bit more -- now you not only need to detect on the clientside the container width and height, but also need to parse any client CSS that may be affecting the image and altering its displayed size.

You could use window.getComputedStyle() on the image to get the list of applicable CSS rules; determining their effects would be... somewhat complicated. There is a partial implementation of this in an answer to this question, for example, though it only includes a tiny handful of the CSS rules that could affect an image or background image's size -- for a general-purpose solution you'd basically be doing the same work that the browser does to lays out the image in the first place.

It may go without saying that it'd be simpler to just have each site just request an appropriately-sized image in the first place.

Community
  • 1
  • 1
Daniel Beck
  • 20,653
  • 5
  • 38
  • 53
  • "Resizing the window after load either triggers new image generation (wasting bandwidth)" Isn't that the same thing that happens with your media queries? Ignoring server time used - the browser still has to fetch a new image... – abagshaw Aug 22 '16 at 18:39
  • 1
    Yes, but with a maximum of three or four separate images, rather than (all possible width values multiplied by all possible height values) separate images. – Daniel Beck Aug 22 '16 at 20:11
0

You can do this by submitting an ajax request on document request, as well as on resize. Then store this information to a session. Then return the scaled image via PHP ie:

<img src="image.php?img=someimg.jpg" />

You said you have server side covered so the javascript would look something like this:

$(function() { 
    function getvp() {
    var vp = { 
        width: $(window).width(), 
      height: $(window).height()
    }
    return vp;
  }
  function submit_vp(vp) { 
     $.ajax({
        method: "POST",
        url: "some.php",
        data: { vpwidth: vp.width, vpheight: vp.height }
  })
  .done(function(msg) {
    //ajax is done
    alert('width: ' + vp.width + ' height: ' + vp.height);
  });
  }

  //Get initial viewport. 
  $(document).ready(function() {
    submit_vp(getvp());
  });
  //Resubmit viewport on resize.
  $(window).resize(function() { 
    submit_vp(getvp());
  });
});
Mike
  • 1,436
  • 9
  • 16
-1

So if I am understanding correctly, you are looking to take an image, and have it resize based on the height and width of the window is that correct?

Check out the JSFiddle I created as an example using % for the height and width. As well as using the background-size: tag, you can select cover or content.

HTML:

<body>
<div class="box1">
<span></span>
</div>
</body>

CSS:

html, body {
  height: 100%;
}
.box1 {
  background: url(http://cdn.wallpapersafari.com/23/44/2mYJfU.jpg) no-repeat;
  height: 100%;
  width: 100%;
  background-size: cover;
}

This may be a good refrence: CSS3 Background-size

Gurgen Grigoryan
  • 265
  • 1
  • 5
  • 17
  • Thanks but this isn't what I am trying to do at all. I'm trying to figure out how much height and width and image **could** occupy in a given orientation and viewport. – abagshaw Aug 22 '16 at 17:56
  • Can you create a div and define the box height and width 100%. Add a tag to it, then use jquery .width() and .height() to get the information you need (how much space it could actually occupy) - this will let you not have to load the large image. – Gurgen Grigoryan Aug 22 '16 at 18:04
-1

If I'm understanding correctly, you want to be able to find the area for a picture, then scale it using server side (GD Library?) scripting, then display the image?

This is to save bandwidth?

I would probably just use a jquery call to find the width of the screen (or a container if you give the container padding), then with AJAX, send the width dimension to your back-end script.

The back-end script would then find out the aspect ratio of the image in question, apply the multiple of the w:h ratio to the width of the returned number and the ratio of the picture, then scale the image to that size and send it back.

html

<div class="container">

</div>

javascript

var width = $('.container').width();
$.post("back-end-script.php", {width:width}, function(data){
    console.log(data); //Do something here with the returned picture
});

graphic backend script (back-end-script.php)

$width = $_POST['width'];
$img = thisimage.jpg;
//Not sure what script you're using, but this is where you'd find the
//img width and height
$img_w = /*image width*/
$img_h = /*image height*/
$img_r = $img_h / $img_w; //This will get a percentage
$new_img_w = $width;
$new_img_h = $new_img_w * $img_r; //This will make the height the right size

/* Then from here, convert your image to the right size and echo it back */

echo $new_img;

Some downfalls of doing it this way: If someone happens to resize their browser, you either have to run a delayed call to get a new image or you'll be stuck with the wrong sized image. Also, you might save more bandwidth if you just came up with 6-10 different image sizes for a responsive web:

<picture class="n-column-image-above__image tnt tnt-image">
    <!--[if IE 9]>
        <video style="display: none;">
    <![endif]-->
    <source media="(min-width: 1144px)" srcset="../img/img_retailer_icon_1077.png, ../img/img_retailer_icon_2154.png 2x"/>
    <source media="(min-width: 768px)" srcset="../img/img_retailer_icon_707.png, ../img/img_retailer_icon_1414.png 2x"/>
    <source media="(min-width: 375px)" srcset="../img/img_retailer_icon_340.png, ../img/img_retailer_icon_680.png 2x"/>
    <source srcset="../img/img_retailer_icon_290.png, ../img/img_retailer_icon_580.png 2x"/>
    <!--[if IE 9]>
        </video>
    <![endif]-->
    <img src="../img/img_retailer_icon_1077.png" alt="REPLACE WITH IMAGE DESCRIPTION"/>
</picture>
ntgCleaner
  • 5,865
  • 9
  • 48
  • 86