views:

320

answers:

6

Can anyone think of a way I can discover a users pixels per inch? I want to ensure that a image displays in a web browser exactly the size I need it to, so using a combination of resolution (which I can get from the user agent) and pixels per inch I could do this.

However, I'm not sure if there is any way to discover a users pixels per inch, ideally using JavaScript or some other non-invasive method.

Any suggestions?

Thanks,

CJ

A: 

Displays today support 96px/inch or 72pixels/inch .

You can get the HTTP request User-Agent header

User-Agent: Mozilla/5.0 (Linux; X11)

this one will tell you the operating system and from here you can make a decision.

Elzo Valugi
I'm also thinking about mobile phone browsers though, and these have far higher levels of and more varied ranges of px/inch hence I was wondering if there's any programmatic way of doing this.
CJ
They've standardised on pretending that, but the actual displays may vary quite a bit -- for example, my netbook has a real DPI of ~170, and my desktop here at work of ~90. Think about it: when you get both 17" and 19" monitors with the same resolution, the actual DPI can't be the same :).
Andrew Aylett
A: 

See also this question on Stack - a duplicate.

This also looks like a novel solution, not sure if it works, though.

Andy Shellam
Has anyone tried this and found out if it works?
CJ
I suspect it will give you 96 on Windows and 72 on OSX, regardless of the real-world DPI, unless the user has explicitly set up their system correctly.
Andrew Aylett
A: 

This may be very tough - even if you somehow manage to scale the rendered image based on dpi, how do you prevent the user from scaling the image in his browser directly?

Have you considered some rich interface technologies like flash or Silverlight? They may give you additional options.

Marek
Do you know if flash be able to give the sort of information I need?
CJ
I'm pretty sure flash can't :(.
Andrew Aylett
+4  A: 

You could do as the drawing packages of old did, and display a stretchable ruler. Have your users drag the virtual ruler until it matches a physical ruler they've put against the screen.

Not a serious suggestion for production use, but probably the only way to actually get the right answer :(.

Andrew Aylett
Thanks for that, I'll bear it in mind :)
CJ
I think this is the only method that will actually work. But it is not very practical.
Jacco
+1  A: 

You could use the following javascript function to get the DPI.

<script type="text/javascript">
   var dpi = {
      v: 0,
      get: function (noCache) {
         if (noCache || dpi.v == 0) {
            e = document.body.appendChild(document.createElement('DIV'));
            e.style.width = '1in';
            e.style.padding = '0';
            dpi.v = e.offsetWidth;
            e.parentNode.removeChild(e);
         }
         return dpi.v;
      }
   }

    alert(dpi.get(true));  // recalculate
    alert(dpi.get(false)); // use cached value
</script>

However, I think it will always return 96 on windows machines.

As far as I know, there is no way for the operating system to determine the actual physical dimensions of the viewport. So, it might very well be that it is actually impossible for software to know the real-life DPI.

However, professionals is certain branches make sure that the on screen DPI matches the real-life DPI. In those case the above javascript would probably be sufficient.

Note:
Tested the above code in Opera 9, IE6 & 7 and Firefox 3.6 on WinXP and Win2k.

Update:
Added the noCache param. But I doubt it will have any effect. I tested it with zoom in FireFox and Opera on the above mentioned windows versions and they keep quoting the DPI as '96', regardless of the amount of zoom. Would be interesting to see what mobile devices make of this.

Jacco
Per the original poster's comment below about mobile browsers:Bear in mind that mobile phone browsers allow users to zoom in and out, so the DPI will be an extremely dynamic value. It may not make sense to cache the value calculated for the DPI.
Dancrumb
@Dancrumb: This also applies to desktop browsers. Many of the new browser versions have zoom functionality. Opera was very early with this, and now others have followed.
awe
Thanks Dan I will be doing some testing with this, I was hoping that something of this sort would be possible :)
CJ
+1  A: 

The safest and easiest would be to tell the browser what size you want the image. CSS supports inch and metrics, so you could specify the image like any of these examples:

<img src="image.png" style="width:15cm;height:10cm;" alt="Centimeters" />
<img src="image.png" style="width:5.9in;height:3.9in;" alt="Inches" />
<img src="image.png" style="width:150mm;height:100mm;" alt="Millimeters" />
awe
I just tried this in firefox on windows, although the units are valid they don't seem to work correctly. On my monitor it was roughly 1.5cm specified = 1cm actual. I don't know what it will be like in other browsers.
PeteT
This is not working at all. The browser will use the default dpi for the operating system for this.
Jacco
Thanks for the interest and testing that idea - v. helpful to me and a real shame something that simple and intuitive doesn't work :( Thanks for the idea though!
CJ
The solution you have accepted relies on setting style using inch just like my solution. The only difference is that I use the style setting to set the size directly on the image, and jacco use the same style to calculate the dpi.I tested my solution in IE 8, Chrome 4, Firefox 3.5.8 and all displayed the same size. When I measured, it was about 1-2mm wrong. My operating system is Windows Vista. I also tried Jacco's method to get the dpi, and then used the result to calculate the image sizes and set them on an image using javascript. The measured size was exactly the same as with my solution!
awe
Conclusion: If all you need to do is set the image size, use my method (it's simpler). If you need the DPI value for other things as well, use Jacco's method. If this is not good enough, I think you have to go with the ruler suggested by Andrew Aylett.
awe