imagesize

Pure-Python library that reads image dimensions and DPI straight from file headers without decoding pixels.

Library
PyPI
v2.0.1
254stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
70/100Good
Development Activity72
Maintenance56
Community72
Maturity60
Momentum20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
61/100Good
Architecture78
Code Quality74
Innovation66
Learning Curve25

imagesize is a lightweight, pure-Python library for extracting image dimensions, DPI, and other header metadata without loading or decoding the actual pixel data. It supports BMP, PNG, JPEG, JPEG 2000, GIF, TIFF, SVG, Netpbm, WebP, AVIF, HEIC, and HEIF, parsing each format’s container structure directly with dedicated format-specific readers rather than depending on a general-purpose imaging library.

Beyond local files and file-like objects, imagesize can read directly from HTTP and HTTPS URLs using byte-range requests, fetching only the bytes needed to resolve size and metadata rather than downloading the whole image, and it falls back transparently to a full download if the server doesn’t support ranges. Version 2.0 added AVIF/HEIC/HEIF support, EXIF-aware rotation handling, and a richer get_info() API returning color depth and channel counts alongside width, height, and DPI.

What You Get

  • Format-specific header parsers for BMP, PNG, JPEG, JPEG 2000, GIF, TIFF, SVG, Netpbm, WebP, AVIF, HEIC, and HEIF
  • A simple get() function returning (width, height) with automatic EXIF-based rotation correction
  • A getDPI() function returning resolution metadata for print-aware workflows
  • A richer get_info() API returning an ImageInfo named tuple with rotation, color depth, and channel count
  • Native support for reading from local paths, file-like objects, and HTTP/HTTPS URLs via byte-range requests

Common Use Cases

  • Web servers computing <img> width/height attributes ahead of time to avoid layout shift
  • Static site generators and CMSs validating or resizing image assets during build
  • Document/PDF pipelines that need image dimensions without pulling in a full imaging dependency
  • Crawlers and asset auditors checking dimensions of remote images without downloading full files

Under The Hood

Architecture The codebase is a single-module library (imagesize/imagesize.py, ~1,330 lines) with no internal layering beyond format-specific parsing functions dispatched from a shared metadata reader; _detect_image_format sniffs the leading bytes of a stream to pick the right per-format reader (_read_png_dpi, _read_jpeg_metadata, _read_tiff_metadata, _read_jp2_metadata, _read_heif_metadata_stream, _read_svg_size, _read_netpbm_size), and the three public entry points (get, getDPI, get_info) all funnel through that shared reader with different toggles rather than duplicating format logic per function. Input abstraction is handled by _open_file, which normalizes paths, file-like objects, and HTTP(S) URLs (via the internal _HttpRangeReader class) into one seekable-stream interface, so every format reader operates against the same read/seek contract regardless of source; _HttpRangeReader layers a small block cache over conditional Range requests, falling back to a full download when a server doesn’t support ranges. Adding a new format is localized to one magic-number branch plus one new _read_* function, a reasonably clean separation for a single-file library.

Tech Stack imagesize is pure Python 3.10+ with zero third-party runtime dependencies, relying entirely on the standard library: struct for binary header unpacking, xml.etree.ElementTree for SVG parsing, urllib.request/urllib.error for the HTTP(S)-URL code path, collections.OrderedDict for the HTTP block cache, and typing/Protocol/NamedTuple for its public type surface. Packaging uses a PEP 621 pyproject.toml with setuptools as the build backend and a dynamic version sourced from imagesize.__version__. CI runs the test suite across Python 3.10 through 3.15 on GitHub Actions using python -m unittest discover, with no separate lint or type-check job.

Code Quality The test suite has one module per concern (test_get.py, test_get_info.py, test_getdpi.py, test_get_filelike.py, test_get_url.py, plus test_performance.py), backed by real sample image fixtures per format. Error handling is deliberate: as of 2.0, get()/getDPI() intentionally return (-1, -1) on parse failure instead of raising, a documented and intentional design change, and internal parsers favor sentinel/default values over letting exceptions propagate from the public API. The public API carries full type hints and a runtime_checkable Protocol formalizes the file-like-object contract instead of relying on duck typing alone. No linter or formatter configuration is present in the repository or wired into CI.

API Design The differentiator is a genuinely dependency-free footprint: instead of requiring a general imaging library just to read a header, it hand-parses each container format’s byte layout directly, and extends that into HTTP(S) sources, fetching only small byte ranges on demand so remote image dimensions can be resolved without downloading the full file. The public surface is intentionally narrow and consistent across all three entry points, sharing the same input types and failure convention, with get_info() as a strict superset that lets callers request only the fields they need. The underlying problem (header-only image size reading) is a well-known pattern, so the ergonomics rather than the concept are what stand out.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search