Skip to content

DPI / PPI Calculator — C# source

Compute screen pixel density (PPI/DPI), dot pitch, physical dimensions, and aspect ratio from any resolution. Solve for PPI from a diagonal, or derive the diagonal from a known PPI - all in your browser.

This is the C# implementation — the same logic the interactive tool runs, in a shareable, citable form.

// =============================================================================
//  DpiPpi.cs — CosmoDev polyglot showcase port of the `dpi-ppi` tool
//  -----------------------------------------------------------------------------
//  Language : C# (C# 12, standard library only)
//  Source:   ported from src/lib/dpi-ppi.ts (the canonical, live TypeScript
//             lib); mirrors src/tool-sources/dpi-ppi/{python.py,rust.rs}
//  License  : display source — part of CosmoDev's polyglot tool pages
//             (dev.cosmolabs.org). Shown verbatim alongside the JS/TS/Go/Rust/
//             Python ports and the other language ports.
//  -----------------------------------------------------------------------------
//  Display pixel-density math. Diagonal length in pixels, pixels-per-inch
//  computed from a known physical diagonal, physical width/height/diagonal in
//  both inches and millimeters, dot pitch in millimeters per pixel, and a
//  reduced aspect ratio — all derived from a pixel resolution.
//
//  Pure, deterministic, side-effect free. A zero divisor does not throw:
//  double division follows IEEE-754, so x / 0.0 yields ±Infinity and
//  0.0 / 0.0 yields NaN — callers should guard with double.IsFinite before
//  display. (The Python port routes every division through a SafeDiv wrapper
//  only because Python raises ZeroDivisionError for float division.)
// =============================================================================

namespace CosmoDev.DpiPpi;

/// <summary>Display pixel-density math.</summary>
public static class DpiPpi
{
    /// <summary>Fixed conversion factor between inches and millimeters.</summary>
    public const double MmPerInch = 25.4;

    /// <summary>Pixels-per-inch result.</summary>
    public readonly record struct Ppi(double Ppi);

    /// <summary>Physical dimensions of a display, in inches and millimeters.</summary>
    public readonly record struct PhysicalSize(
        double WidthIn,
        double HeightIn,
        double DiagonalIn,
        double WidthMm,
        double HeightMm);

    /// <summary>
    /// Diagonal length in pixels: √(w² + h²).
    /// The sign of the inputs is irrelevant because both terms are squared.
    /// </summary>
    public static double DiagonalPixels(double w, double h) =>
        Math.Sqrt(w * w + h * h);

    /// <summary>Pixels per inch, given a resolution and a known physical diagonal in inches.</summary>
    public static Ppi ComputePpi(double w, double h, double diagonalInches) =>
        new(DiagonalPixels(w, h) / diagonalInches);

    /// <summary>
    /// Derive inches and millimeters from a resolution and a ppi. The diagonal
    /// is recomputed from the derived inch dimensions so it stays consistent
    /// with the width/height values.
    /// </summary>
    public static PhysicalSize PhysicalSizeFromPpi(double w, double h, double ppi)
    {
        double widthIn = w / ppi;
        double heightIn = h / ppi;
        return new PhysicalSize(
            WidthIn: widthIn,
            HeightIn: heightIn,
            DiagonalIn: DiagonalPixels(widthIn, heightIn),
            WidthMm: widthIn * MmPerInch,
            HeightMm: heightIn * MmPerInch);
    }

    /// <summary>Dot pitch (pixel size) in millimeters per pixel: 25.4 / ppi.</summary>
    public static double DotPitch(double ppi) => MmPerInch / ppi;

    /// <summary>
    /// Integer greatest common divisor via Euclid's algorithm, used to reduce
    /// aspect ratios. Inputs are truncated toward zero and taken in absolute
    /// value first, so the sign and fractional part of the inputs never
    /// matter. (The casts assume finite inputs — the w &gt; 0 / h &gt; 0
    /// guard in <see cref="AspectRatio"/> has already rejected NaN and
    /// negatives, and real resolutions are far below the i64 range.)
    /// </summary>
    private static long Gcd(double a, double b)
    {
        long x = Math.Abs((long)Math.Truncate(a));
        long y = Math.Abs((long)Math.Truncate(b));
        while (y != 0)
        {
            (x, y) = (y, x % y);
        }

        return x;
    }

    /// <summary>
    /// Reduced aspect ratio as "w:h" (e.g. "16:9"). Returns "-" when either
    /// side is not a positive number (this also covers NaN, since every
    /// comparison with NaN is false).
    /// </summary>
    public static string AspectRatio(double w, double h)
    {
        if (!(w > 0) || !(h > 0))
        {
            return "-";
        }

        long g = Gcd(w, h);
        if (g == 0)
        {
            return "-";
        }

        long wi = (long)Math.Truncate(w);
        long hi = (long)Math.Truncate(h);
        return $"{wi / g}:{hi / g}";
    }
}

Also available in 13 other languages

Every CosmoDev tool ships its pure logic in TypeScript (web) and Go (CLI), with authored implementations in a dozen-plus languages — the same contract, ported. Compare all languages side by side →