3

I have

?(New System.Windows.LengthConverter()).ConvertFrom("1cm")
37.795275590551178 {Double}
    Double: 37.795275590551178

So, in 1cm I have 37.795275590551178px WPF pixels.

My problem is how I convert back from px to cm?

serhio
  • 28,010
  • 62
  • 221
  • 374

3 Answers3

18

As in WPF we deal with DeviceIndependentUnits (DIU, named, conventionally "px"), that units does not depend of the device or screen resolution.

Actually the factors used in .NET Framework (4), for 'px', 'in', 'cm' and 'pt' respectively

// System.Windows.LengthConverter
private static double[] PixelUnitFactors = new double[]
{
    1.0,
    96.0,
    37.795275590551178,
    1.3333333333333333
};

So, we have

private struct PixelUnitFactor
{
    public const double Px = 1.0;
    public const double Inch = 96.0;
    public const double Cm = 37.7952755905512;
    public const double Pt = 1.33333333333333;
}    

public double CmToPx(double cm)
{
    return cm * PixelUnitFactor.Cm;
}

public double PxToCm(double px)
{
    return px / PixelUnitFactor.Cm;
}
serhio
  • 28,010
  • 62
  • 221
  • 374
  • This doesn't make sense to me. You're telling me on a screen that is 120DPI (returned by Win32 API GetDeviceCaps()), that an inch is still 96 DPI in WPF? How does WPF account for that discrepancy? Does the width of the pixel increase by 20%? – Andy Feb 03 '17 at 02:06
  • 2
    Yes it does. 1 pixel in WPF is sort of defined when on a 96 dpi screen. When your screen has a higher resolution the size gets increased. – pinki Feb 11 '17 at 14:41
  • this formula is not complete. you need to take in account the physical screen size – Ashraf Sayied-Ahmad May 03 '17 at 07:13
  • 1
    OP did not specify that he wanted the total pixels on his screen. He wanted a way to convert pixels to centimeters. So long as the DPI is the same, it doesn't matter what the screen size is. The algorithm will still be the same. – CodeWarrior May 03 '17 at 19:12
4

This is a problem of the computer industry using inches. There are 96 pixels per inch. There are 2.54 cm per inch. 37.795275590551178 (1 cm) * 2.54 = 95.9999999999997 pixels (we'll call it 96).

You could always create an application level constant for 37.795275590551178, or you could use inches and convert back and forth inches and centimeters...

For converting px to cm, you could convert px to inch to cm, or you could use the above constant and divide by it to get centimeters.

96 pixels / 37.795275590551178 = 2.54 cm.

Here is another SO post about it: Centimeter to pixel

Community
  • 1
  • 1
CodeWarrior
  • 7,388
  • 7
  • 51
  • 78
2

I had a similar trouble, but de WPF makes the calculations to adjust the logical pixels to physical pixels. Maybe this piece of code can help you.

public struct PixelUnitFactor
{
    public const double Px = 1.0;
    public const double Inch = 96.0;
    public const double Cm = 37.795275590551178;
    public const double Pt = 1.33333333333333;
}

public struct CmUnitFactor
{
    public const double Px = 0.0264583333333333;
    public const double Inch = 2.54;
    public const double Cm = 1.0;
    public const double Pt = 0.035277778;
}

public struct InUnitFactor
{
    public const double Px = 0.0104166666666667;
    public const double Inch = 1.0;
    public const double Cm = 0.3937007874015748;
    public const double Pt = 0.013888888888889;
}

public struct PtUnitFactor
{
    public const double Px = 0.75;
    public const double Inch = 72.0;
    public const double Cm = 28.346456693;
    public const double Pt = 1.0;
}

public class FormsEvent
{

    //FUNCIONES PARA CONVERTIR PIXELS EN CENTÍMETROS, PULGADAS Y PUNTOS
    public static double Convertir_PxToCm(double px) { return px / PixelUnitFactor.Cm; }
    public static double Convertir_PxToIn(double px) { return px / PixelUnitFactor.Inch; }
    public static double Convertir_PxToPt(double px) { return px / PixelUnitFactor.Pt; }

    //FUNCIONES PARA CONVERTIR CENTÍMETROS EN PIXELS, PULGADAS Y PUNTOS
    public static double Convertir_CmToPx(double cm) { return cm / CmUnitFactor.Px; }
    public static double Convertir_CmToIn(double cm) { return cm / CmUnitFactor.Inch; }
    public static double Convertir_CmToPt(double cm) { return cm / CmUnitFactor.Pt; }

    //FUNCIONES PARA CONVERTIR PULGADAS EN PIXELS, CENTÍMETROS Y PUNTOS
    public static double Convertir_InToPx(double inches) { return inches / InUnitFactor.Px; }
    public static double Convertir_InToCm(double inches) { return inches / InUnitFactor.Cm; }
    public static double Convertir_InToPt(double inches) { return inches / InUnitFactor.Pt; }

    //FUNCIONES PARA CONVERTIR PUNTOS EN PIXELS, PULGADAS Y CENTÍMETROS
    public static double Convertir_PtToPx(double pt) { return pt / PtUnitFactor.Px; }
    public static double Convertir_PtToCm(double pt) { return pt / PtUnitFactor.Cm; }
    public static double Convertir_PtToIn(double pt) { return pt / PtUnitFactor.Inch; }