9

I am looking to convert pixes to inches and vice versa. I understand that I need DPI, but I am not sure how to get this information (e.g. I don't have the Graphics object, so that's not an option).

Is there a way?

TylerH
  • 20,799
  • 66
  • 75
  • 101
AngryHacker
  • 59,598
  • 102
  • 325
  • 594

3 Answers3

8

On a video device, any answer to this question is typically not very accurate. The easiest example to use to see why this is the case is a projector. The output resolution is, say, 1024x768, but the DPI varies by how far away the screen is from the projector apeture. WPF, for example, always assumes 96 DPI on a video device.

Presuming you still need an answer, regardless of the accuracy, and you don't have a Graphics object, you can create one from the screen with some P/Invoke and get the answer from it.

Single xDpi, yDpi;

IntPtr dc = GetDC(IntPtr.Zero);

using(Graphics g = Graphics.FromHdc(dc))
{
    xDpi = g.DpiX;
    yDpi = g.DpiY;
}

if (ReleaseDC(IntPtr.Zero) != 0)
{
    // GetLastError and handle...
}


[DllImport("user32.dll")]
private static extern IntPtr GetDC(IntPtr hwnd);    
[DllImport("user32.dll")]
private static extern Int32 ReleaseDC(IntPtr hwnd);
codekaizen
  • 26,990
  • 7
  • 84
  • 140
6

There's, physically, no real way without knowing the DPI. Pixels are discrete, inches are not, if you're talking inches on your monitor, you need to know (at the very least) the resolution (and pixel aspect ratio) and the size of the visible monitor area in order to calculate your DPI. The resolution is usually possible to fetch somewhere (I'm not a C# or .NET programmer, so I can't help you there), but the size of the monitor is usually not available. If an estimate is good enough then have the user enter the size of the monitor (i.e. 21" or whatever) and solve for DPI:

(resX/DPI)^2 + (resY/DPI)^2 = screenDiagonal^2

giving (assuming you know the diagonal and the resolution)

DPI = sqrt(resX^2+resY^2)/screenDiagonal

This is just an estimate, as monitors are never exactly 21" (.. or whatever), and the pixel aspect ratio is hardly ever exactly 1:1.

If you're talking inches on paper, then, quite naturally you need to know the DPI of your printer (or, more accurately, the current printer settings).

falstro
  • 34,597
  • 9
  • 72
  • 86
  • So given that I don't have access to the Graphics object, how do I calculate the DPI? – AngryHacker Jan 23 '09 at 22:43
  • Solve the equation for DPI, assuming the rest is known. – falstro Jan 23 '09 at 22:52
  • How would I know the diagonal length of the monitor? My app will run on computers I don't control. – AngryHacker Jan 23 '09 at 23:00
  • Either you make a rough estimate and assume everyone has a 19" or 21" or something; if it's really important, then you have to ask the user, no one else knows (see answer commenting on projectors), but in this case you'll probably want to use some other technology to get a more accurate answer. – falstro Jan 24 '09 at 10:08
  • This is a pretty useless answer. He's looking for a system call to tell him what windows is assuming is the DPI (as am I). – mmr Jul 16 '09 at 04:57
  • @mmr - check the answer below. – codekaizen Aug 10 '09 at 22:39
1

You can create the Graphics object simply by calling this.CreateGraphics() (or more generally Control.CreateGraphics()) and then use the DpiX and DpiY properties as you seem to know. Just remember to dispose the graphics object after creating it (ideally with a Using statement).

If you're not using WinForms, then please let us know what sort of application it is.

Noldorin
  • 144,213
  • 56
  • 264
  • 302
  • I can't. I am writing code in a code-behind file of an ActiveReports report sheet. It does not have these properties. – AngryHacker Jan 23 '09 at 22:34
  • He did state that he's using WPF, which is not WinForms. Using the two together can cause serious headaches. – mmr Jul 16 '09 at 04:57
  • @mmr: No, he did not state he is using WPF. In fact, the reference to the `Graphic` seems to strongly imply WinForms. Thanks for the down-vote, anyway. – Noldorin Jul 16 '09 at 07:47