DPI / PPI Calculator — Swift 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 Swift implementation — the same logic the interactive tool runs, in a shareable, citable form.
// =============================================================================
// DpiPpi.swift — CosmoDev polyglot showcase port of the `dpi-ppi` tool
// -----------------------------------------------------------------------------
// Language : Swift (5.9, 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 trap:
// Double division follows IEEE-754, so x / 0.0 yields ±.infinity and
// 0.0 / 0.0 yields .nan — callers should guard with isFinite before
// display. (The Python port routes every division through a safeDiv wrapper
// only because Python raises ZeroDivisionError for float division.)
// =============================================================================
/// Display pixel-density math.
public enum DpiPpi {
/// Fixed conversion factor between inches and millimeters.
private static let mmPerInch: Double = 25.4
/// Pixels-per-inch result.
public struct Ppi: Equatable {
public let ppi: Double
public init(ppi: Double) { self.ppi = ppi }
}
/// Physical dimensions of a display, in inches and millimeters.
public struct PhysicalSize: Equatable {
public let widthIn: Double
public let heightIn: Double
public let diagonalIn: Double
public let widthMm: Double
public let heightMm: Double
public init(
widthIn: Double,
heightIn: Double,
diagonalIn: Double,
widthMm: Double,
heightMm: Double
) {
self.widthIn = widthIn
self.heightIn = heightIn
self.diagonalIn = diagonalIn
self.widthMm = widthMm
self.heightMm = heightMm
}
}
/// Diagonal length in pixels: √(w² + h²).
/// The sign of the inputs is irrelevant because both terms are squared.
public static func diagonalPixels(_ w: Double, _ h: Double) -> Double {
(w * w + h * h).squareRoot()
}
/// Pixels per inch, given a resolution and a known physical diagonal in inches.
public static func computePpi(_ w: Double, _ h: Double, diagonalInches: Double) -> Ppi {
Ppi(ppi: diagonalPixels(w, h) / diagonalInches)
}
/// 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.
public static func physicalSize(_ w: Double, _ h: Double, ppi: Double) -> PhysicalSize {
let widthIn = w / ppi
let heightIn = h / ppi
return PhysicalSize(
widthIn: widthIn,
heightIn: heightIn,
diagonalIn: diagonalPixels(widthIn, heightIn),
widthMm: widthIn * mmPerInch,
heightMm: heightIn * mmPerInch)
}
/// Dot pitch (pixel size) in millimeters per pixel: 25.4 / ppi.
public static func dotPitch(_ ppi: Double) -> Double {
mmPerInch / ppi
}
/// Saturating Double → Int64 truncation, mirroring Rust's `as i64` cast
/// semantics (NaN → 0, ±out-of-range → min/max). Avoids the runtime trap
/// of `Int64(x)` on pathological ±inf inputs; real display sizes are
/// finite.
private static func truncToI64(_ x: Double) -> Int64 {
let t = x.rounded(.towardZero)
if t.isNaN { return 0 }
if t >= 9_223_372_036_854_775_808.0 { return Int64.max } // 2^63
if t < -9_223_372_036_854_775_808.0 { return Int64.min }
return Int64(t)
}
/// 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.
private static func gcd(_ a: Double, _ b: Double) -> Int64 {
var x = truncToI64(a.magnitude)
var y = truncToI64(b.magnitude)
while y != 0 {
(x, y) = (y, x % y)
}
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).
public static func aspectRatio(_ w: Double, _ h: Double) -> String {
if !(w > 0) || !(h > 0) {
return "-"
}
let g = gcd(w, h)
if g == 0 {
return "-"
}
return "\(truncToI64(w) / g):\(truncToI64(h) / 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 →