DPI / PPI Calculator — Rust 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 Rust implementation — the same logic the interactive tool runs, in a shareable, citable form.
//! Display pixel-density math (Rust port).
//!
//! Pure, deterministic, never panics. Non-positive inputs that would cause
//! division by zero produce `NaN` or infinity (IEEE-754 behavior — Rust's
//! `f64` division follows the standard and does not panic) rather than
//! returning a `Result`; callers should guard with `f64::is_finite` before
//! display.
//!
//! CosmoDev polyglot showcase port of `dpi-ppi`, ported from
//! `src/lib/dpi-ppi.ts`. Display source — part of CosmoDev's polyglot tool pages.
/// Fixed conversion factor between inches and millimeters.
const MM_PER_INCH: f64 = 25.4;
/// A resolution (width and height) in pixels, shared by the calculations
/// that consume a pixel grid.
#[derive(Clone, Copy, Debug)]
pub struct Resolution {
pub w: f64,
pub h: f64,
}
/// Pixels-per-inch result.
#[derive(Clone, Copy, Debug)]
pub struct Ppi {
pub ppi: f64,
}
/// Physical dimensions of a display, in both inches and millimeters.
#[derive(Clone, Copy, Debug)]
pub struct PhysicalSize {
pub width_in: f64,
pub height_in: f64,
pub diagonal_in: f64,
pub width_mm: f64,
pub height_mm: f64,
}
/// Diagonal length in pixels: √(w² + h²).
/// The sign of the inputs is irrelevant because both terms are squared.
pub fn diagonal_pixels(w: f64, h: f64) -> f64 {
(w * w + h * h).sqrt()
}
/// Pixels per inch, given a resolution and a known physical diagonal in inches.
pub fn compute_ppi(r: Resolution, diagonal_inches: f64) -> Ppi {
Ppi {
ppi: diagonal_pixels(r.w, r.h) / diagonal_inches,
}
}
/// 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.
pub fn physical_size(r: Resolution, ppi: f64) -> PhysicalSize {
let width_in = r.w / ppi;
let height_in = r.h / ppi;
PhysicalSize {
width_in,
height_in,
diagonal_in: diagonal_pixels(width_in, height_in),
width_mm: width_in * MM_PER_INCH,
height_mm: height_in * MM_PER_INCH,
}
}
/// Dot pitch (pixel size) in millimeters per pixel: 25.4 / ppi.
pub fn dot_pitch(ppi: f64) -> f64 {
MM_PER_INCH / ppi
}
/// 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.
fn gcd(a: f64, b: f64) -> i64 {
let mut x = a.trunc().abs() as i64;
let mut y = b.trunc().abs() as i64;
while y != 0 {
let t = y;
y = x % y;
x = t;
}
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).
pub fn aspect_ratio(w: f64, h: f64) -> String {
if !(w > 0.0) || !(h > 0.0) {
return String::from("-");
}
let g = gcd(w, h);
if g == 0 {
return String::from("-");
}
let wi = w.trunc() as i64;
let hi = h.trunc() as i64;
format!("{}:{}", 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 →