Skip to content

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

# =============================================================================
#  dpi-ppi.rb — CosmoDev polyglot showcase port of the `dpi-ppi` tool
#  -----------------------------------------------------------------------------
#  Language : Ruby (3.2+, 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 raise:
#  Float division follows IEEE-754 (1.0 / 0.0 => Infinity, 0.0 / 0.0 => NaN);
#  only Integer division by zero raises in Ruby, and every value here stays a
#  Float — callers should guard with finite? before display. (The Python port
#  routes divisions through a safe_div wrapper only because Python raises
#  ZeroDivisionError for floats too.)
# =============================================================================

module DpiPpi
  # Fixed conversion factor between inches and millimeters.
  MM_PER_INCH = 25.4

  # Pixels-per-inch result.
  Ppi = Struct.new(:ppi, keyword_init: true)

  # Physical dimensions of a display, in inches and millimeters.
  PhysicalSize = Struct.new(:width_in, :height_in, :diagonal_in, :width_mm, :height_mm, keyword_init: true)

  class << self
    # Diagonal length in pixels: √(w² + h²).
    # The sign of the inputs is irrelevant because both terms are squared.
    def diagonal_pixels(w, h)
      Math.sqrt(w * w + h * h)
    end

    # Pixels per inch, given a resolution and a known physical diagonal in inches.
    def compute_ppi(w, h, diagonal_inches)
      Ppi.new(ppi: diagonal_pixels(w, h) / diagonal_inches)
    end

    # 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.
    def physical_size(w, h, ppi)
      width_in = w / ppi
      height_in = h / ppi
      PhysicalSize.new(
        width_in: width_in,
        height_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
      )
    end

    # Dot pitch (pixel size) in millimeters per pixel: 25.4 / ppi.
    def dot_pitch(ppi)
      MM_PER_INCH / ppi
    end

    # 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). Integer#gcd computes the
    # non-negative greatest common divisor of the truncated values directly —
    # the hand-rolled Euclid of the Python and Rust ports in one stdlib call.
    def aspect_ratio(w, h)
      return '-' unless w > 0 && h > 0

      g = w.truncate.gcd(h.truncate)
      return '-' if g.zero?

      "#{w.truncate / g}:#{h.truncate / g}"
    end
  end
end

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 →