Skip to content

DPI / PPI Calculator — PHP 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 PHP implementation — the same logic the interactive tool runs, in a shareable, citable form.

<?php
/**
 * Display pixel-density math (PHP port).
 *
 * Pure, deterministic, never throws. Non-positive inputs that would cause
 * division by zero produce NAN or INF (mirroring JavaScript's IEEE-754
 * behavior) rather than throwing — callers should guard with is_finite()
 * before display.
 *
 * Note: PHP 8 raises DivisionByZeroError on a float `/0`. To stay output-
 * equivalent with the JavaScript reference (which yields Inf/NaN), every
 * division in this module is routed through `safeDiv`.
 *
 * CosmoDev polyglot showcase port of `dpi-ppi`, ported from
 * src/lib/dpi-ppi.ts. Display source — part of CosmoDev's polyglot tool pages.
 */

const MM_PER_INCH = 25.4;

/**
 * IEEE-754-style float division.
 *
 * Returns +/-INF (or NAN for the 0/0 case) when the divisor is zero, instead
 * of letting PHP raise DivisionByZeroError. This keeps results byte-for-byte
 * equivalent to the JavaScript reference implementation.
 */
function safeDiv(float $n, float $d): float
{
    if ($d == 0.0) {
        if ($n == 0.0) {
            return NAN;
        }
        return $n > 0.0 ? INF : -INF;
    }
    return $n / $d;
}

/**
 * Diagonal length in pixels: √(w² + h²).
 * The sign of the inputs is irrelevant because both terms are squared.
 */
function diagonalPixels(float $w, float $h): float
{
    return sqrt($w * $w + $h * $h);
}

/**
 * Pixels per inch, given a resolution and a known physical diagonal (inches).
 */
function computePpi(float $w, float $h, float $diagonalInches): array
{
    return ['ppi' => safeDiv(diagonalPixels($w, $h), $diagonalInches)];
}

/**
 * Physical dimensions of a display (inches and millimeters), derived from a
 * resolution and a ppi. The diagonal is recomputed from the derived inch
 * dimensions so it stays consistent with the width/height.
 */
function physicalSize(float $w, float $h, float $ppi): array
{
    $widthIn  = safeDiv($w, $ppi);
    $heightIn = safeDiv($h, $ppi);
    return [
        'widthIn'    => $widthIn,
        'heightIn'   => $heightIn,
        'diagonalIn' => diagonalPixels($widthIn, $heightIn),
        'widthMm'    => $widthIn  * MM_PER_INCH,
        'heightMm'   => $heightIn * MM_PER_INCH,
    ];
}

/**
 * Dot pitch (pixel size) in millimeters per pixel: 25.4 / ppi.
 */
function dotPitch(float $ppi): float
{
    return safeDiv(MM_PER_INCH, $ppi);
}

/**
 * Integer gcd via Euclid's algorithm, used to reduce aspect ratios. Inputs
 * are truncated toward zero (the `(int)` cast truncates) and taken in
 * absolute value first, so the sign and fractional part never matter.
 */
function gcd(float $a, float $b): int
{
    $x = abs((int) $a);
    $y = abs((int) $b);
    while ($y !== 0) {
        $t = $y;
        $y = $x % $y;
        $x = $t;
    }
    return $x;
}

/**
 * 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).
 */
function aspectRatio(float $w, float $h): string
{
    if (!($w > 0) || !($h > 0)) {
        return '-';
    }
    $g = gcd($w, $h);
    if ($g === 0) {
        return '-';
    }
    // Both operands are exact integers and g divides each evenly, so PHP
    // returns an int here — the string form is a clean "16", not "16.0".
    $wi = (int) $w;
    $hi = (int) $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 →