views:

355

answers:

3

Hey, I need to know active screen DPI on Linux and Mac OS. I think on linux xlib might be useful, but I can't find a way how to get currect DPI. I want this information to get real screen size in inches.

Thanks in advance!

+2  A: 

In X on Linux, call XOpenDisplay() to get the Display, then use DisplayWidthMM() and DisplayHeightMM() together with DisplayWidth() and DisplayHeight() to compute the DPI.

On the Mac, there's almost certainly a more native API to use than X. Mac OS X does not run X Window by default, it has a native windowing environment.

unwind
A: 

You can use NSScreen to get the dimensions of the attached display(s) in pixels, but this won't give you the physical size/PPI of the display and in fact I don't think there are any APIs that will be able to do this reliably.

You can ask a window for its resolution like so:

NSDictionary* deviceDescription = [window deviceDescription];
NSSize resolution = [[deviceDescription objectForKey:NSDeviceResolution] sizeValue];

This will currently give you an NSSize of {72,72} for all screens, no matter what their actual PPI. The only thing that make this value change is changing the scaling factor in the Quartz Debug utility, or if Apple ever turns on resolution-independent UI. You can obtain the current scale factor by calling:

[[NSScreen mainScreen] userSpaceScaleFactor];

If you really must know the exact resolution (and I'd be interested to know why you think you do), you could create a screen calibration routine and have the user measure a line on-screen with an actual physical ruler. Crude, yes, but it will work.

Rob Keniger
-1 Answer doesn't answer the question.
MaxVT
That's because answering the question is not possible, which is what my answer says. You CANNOT get a physically accurate measurement of the display using software alone. I don't think my answer deserved a ‑1.
Rob Keniger
A: 

I cobbled this together from xdpyinfo... Compile with: gcc -Wall -o getdpi getdpi.c -lX11

/* Get dots per inch 
 */
static void get_dpi(int *x, int *y)
{
    double xres, yres;
    Display *dpy;
    char *displayname = NULL;
    int scr = 0; /* Screen number */

    if( (NULL == x) || (NULL == y)){ return ; }

    dpy = XOpenDisplay (displayname);

    /*
     * there are 2.54 centimeters to an inch; so there are 25.4 millimeters.
     *
     *     dpi = N pixels / (M millimeters / (25.4 millimeters / 1 inch))
     *         = N pixels / (M inch / 25.4)
     *         = N * 25.4 pixels / M inch
     */
    xres = ((((double) DisplayWidth(dpy,scr)) * 25.4) / 
        ((double) DisplayWidthMM(dpy,scr)));
    yres = ((((double) DisplayHeight(dpy,scr)) * 25.4) / 
        ((double) DisplayHeightMM(dpy,scr)));

    *x = (int) (xres + 0.5);
    *y = (int) (yres + 0.5);

    XCloseDisplay (dpy);
}
jbal