DPI / PPI Calculator — Go 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 Go implementation — the same logic the interactive tool runs, in a shareable, citable form.
// Package dpippi is the Go twin of CosmoDev's src/lib/dpi-ppi.ts (dual source:
// the web lib is TypeScript, the CLI lib is Go — kept in lock-step). Pure +
// deterministic, never panics. The table-driven tests in dpi-ppi_test.go share
// vectors with src/lib/dpi-ppi.test.ts so the two implementations are held to
// the same contract.
//
// The logic mirrors the TS lib exactly. Non-positive inputs that cause a
// division by zero produce NaN or +Inf — documented IEEE 754 float64 behavior,
// identical to JS — rather than panicking. Callers should guard with
// math.IsFinite before display.
package dpippi
import (
"fmt"
"math"
)
// MmPerInch is the millimeters-per-inch conversion factor (25.4). Mirrors the
// private MM_PER_INCH constant in src/lib/dpi-ppi.ts.
const MmPerInch = 25.4
// DiagonalPixels returns the diagonal length in pixels: √(w² + h²). The sign of
// the inputs is irrelevant because they are squared. It mirrors
// diagonalPixels() in src/lib/dpi-ppi.ts.
func DiagonalPixels(w, h float64) float64 {
return math.Sqrt(w*w + h*h)
}
// PpiInput is the input to ComputePpi: a resolution plus a known physical
// diagonal in inches. It mirrors the {w, h, diagonalInches} object in the TS
// lib.
type PpiInput struct {
W float64
H float64
DiagonalInches float64
}
// PpiResult holds the pixels-per-inch value derived from a resolution and a
// known diagonal. It mirrors the {ppi} object returned by computePpi().
type PpiResult struct {
Ppi float64
}
// ComputePpi derives pixels-per-inch from a resolution and a known diagonal
// (inches). A zero diagonal with a non-zero resolution yields +Inf; a fully
// zero input yields NaN — mirroring JS (never panics). It mirrors
// computePpi() in src/lib/dpi-ppi.ts.
func ComputePpi(in PpiInput) PpiResult {
return PpiResult{Ppi: DiagonalPixels(in.W, in.H) / in.DiagonalInches}
}
// SizeInput is the input to PhysicalSize: a resolution plus a pixel density
// (ppi). It mirrors the {w, h, ppi} object in the TS lib.
type SizeInput struct {
W float64
H float64
Ppi float64
}
// SizeResult holds the physical dimensions (inches and millimeters) of a
// display derived from its resolution and pixel density. It mirrors the object
// returned by physicalSize().
type SizeResult struct {
WidthIn float64
HeightIn float64
DiagonalIn float64
WidthMm float64
HeightMm float64
}
// PhysicalSize computes the physical dimensions of a display from its
// resolution and ppi, returning inches and millimeters. A zero ppi yields +Inf
// (non-zero resolution) or NaN (fully-zero input) — mirroring JS (never
// panics). It mirrors physicalSize() in src/lib/dpi-ppi.ts.
func PhysicalSize(in SizeInput) SizeResult {
widthIn := in.W / in.Ppi
heightIn := in.H / in.Ppi
return SizeResult{
WidthIn: widthIn,
HeightIn: heightIn,
DiagonalIn: DiagonalPixels(widthIn, heightIn),
WidthMm: widthIn * MmPerInch,
HeightMm: heightIn * MmPerInch,
}
}
// DotPitch returns the pixel size in millimeters per pixel (25.4 / ppi). A zero
// ppi yields +Inf — mirroring JS (never panics). It mirrors dotPitch() in
// src/lib/dpi-ppi.ts.
func DotPitch(ppi float64) float64 {
return MmPerInch / ppi
}
// gcd is the integer gcd (Euclid's algorithm) computed over the truncated,
// absolute values of its inputs. It is used to reduce aspect ratios and mirrors
// the private gcd() helper in src/lib/dpi-ppi.ts.
func gcd(a, b float64) float64 {
x := math.Abs(math.Trunc(a))
y := math.Abs(math.Trunc(b))
for y != 0 {
x, y = y, math.Mod(x, y)
}
return x
}
// AspectRatio returns the reduced aspect ratio "w:h" (e.g. "16:9"), or "-" if
// either side is non-positive or the gcd collapses to zero. It mirrors
// aspectRatio() in src/lib/dpi-ppi.ts.
func AspectRatio(w, h float64) string {
if !(w > 0) || !(h > 0) {
return "-"
}
g := gcd(w, h)
if g == 0 {
return "-"
}
return fmt.Sprintf("%d:%d", int64(math.Trunc(w)/g), int64(math.Trunc(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 →