Methodology & Accuracy

Every tool on FileConverters is a thin interface over a set of small, pure, automatically tested functions. This page documents how the pipeline actually works — detection, conversion, verification — and, just as importantly, what it deliberately does not do, so you can judge exactly how far to trust each output.

Files are identified by content, not name

The first thing any tool does with a file is read its leading bytes and match them against the format signatures: \x89PNG, FF D8 FF for JPEG,RIFF…WEBP, GIF87a/GIF89a, and BM for BMP. The filename's extension is compared against that detection: a file namedphoto.png whose bytes are JPEG gets a visible notice and is converted from what it actually is. Animated WebP is recognized from the VP8X animation flag and ANIM chunks; animated GIF by counting image descriptors — so the "first frame only" caveat appears exactly when it applies. HEIC is identified by parsing the ISO-BMFF ftyp box — major and compatible brands (heic, heix, hevc, hevx, mif1,msf1) read from the box structure, bounded by the declared box size, never by substring-searching the file. AVIF — the same container, AV1-coded — is detected from its own brands (avif, avis) by the same box parser, with explicitly HEVC-coded brands taking precedence, and the avis image-sequence brand drives the same "first frame only" caveat that animated GIF and WebP get.

The conversion pipeline

Decoding uses the browser's own codecs via createImageBitmap withimageOrientation: 'from-image', which applies EXIF rotation so phone photos come out upright. The pixels are drawn to a canvas — composited over a background color first whenever the target format cannot represent transparency (JPEG; the page asks for the color before converting) — and re-encoded by the browser's PNG, JPEG, or WebP encoder, or by one of the two self-hosted encoders described below (MozJPEG on the Compress JPEG lane, libavif+aom for AVIF output). Which conversions need flattening, which take a quality parameter, and what the output filename becomes are decided by a pure planning module with its own tests, not ad-hoc in the UI.

HEIC decoding — the one third-party decoder on the site

Every other tool here decodes with the browser's own codecs. HEIC is the exception, because no browser ships a HEIC decoder: the two HEIC pages loadlibheif — © struktur AG and contributors, licensedLGPL-3.0 — compiled to WebAssembly from pinned upstream source, together with itslibde265 HEVC decoder from the same upstream family, also LGPL. The upstream codec source is compiled without source modifications, self-hosted from this site's own origin, and loaded at runtime as a separately replaceable module in a dedicated worker (a script plus a.wasm file under /vendor/libheif/) — never compiled into the site's own JavaScript — so anyone can inspect it, verify its checksums, or substitute their own build. Source code is atgithub.com/strukturag/libheif; exact versions, commits, checksums, and the reproducible build recipe are in the project's provenance record. The full license text ships alongside the module at/vendor/libheif/LICENSE.txt. Decoding still happens entirely in your browser: the module is fetched from this site, and your photo never leaves the tab. Why a third-party decoder at all? Because "convert my iPhone photo" is the single most common conversion request there is, and the alternative — uploading your camera roll to someone's server — is exactly what this site exists to avoid.

Vendored encoders — MozJPEG and libavif + aom

Two tools go beyond the browser's built-in encoders, using the same self-hosting arrangement as libheif: open-source codecs compiled from pinned upstream source, served from this site's own origin as separately replaceable files, fetched lazily only when a file is actually dropped, and run in bounded workers entirely in your browser.

Every vendored file's exact size and SHA-256 is pinned by automated tests, and every codec build uses immutable upstream commits, so served bytes cannot drift silently. AVIFdecoding (AVIF to JPG,AVIF to PNG) deliberately vendors nothing: current Chrome and Edge, Firefox 93+, and Safari 16.4+ decode AVIF natively, so those pages use the browser's own codec with a runtime feature probe and a plain-language notice when a browser cannot.

Why the site encodes AVIF but never HEIC

AVIF and HEIC are structurally siblings — the same HEIF container around a modern video codec — but they live under opposite legal regimes. HEIC's HEVC codec is covered by commercial patent pools, which is why browsers do not ship HEVC encoders and why this site's libheif build is decode-only: producing HEIC files would require licensing terms that a free, in-browser tool cannot honestly satisfy. AVIF's AV1 codec was developed by the Alliance for Open Media to be royalty-free under an explicit patent grant, which is why every current browser reads it and why this site is comfortable shipping an encoder for it. Practically: HEIC-class compression, or better, in a format the web actually reads — so conversions here go from HEIC andto AVIF, never the reverse.

What re-encoding does to metadata

Canvas re-encoding strips all embedded metadata: EXIF (including GPS location, camera model, and timestamps), color-profile tags, and text chunks. We present this as both a feature and a caveat, because it is both — publishing a converted photo cannot leak where it was taken, and equally, photographers lose copyright fields and ICC profiles, so originals should be kept. Orientation is applied during decoding, before metadata is discarded, so uprightness survives even though the orientation tag does not.

Every output is verified before download

A download button on this site means the output has already been checked: the produced bytes are sniffed with the same magic-byte detector applied to inputs (which catches a browser silently substituting PNG when it cannot encode WebP — reported as an honest error, never a mislabeled file), and the blob is re-decoded to confirm its pixel dimensions match the plan. File sizes shown are the output blob's true byte count. Where a result row shows a percent change, it is computed from those two measured byte counts for your file — the site publishes no blanket compression percentages anywhere, because no percentage is true for every image, and a result that comes out larger says "larger — keep your original" in the same breath.

The compress-to-target search

"Make this fit under N kilobytes" is solved by measurement, not prediction: the compressor encodes at maximum quality, then binary-searches the quality range — bracketing between the highest quality known to fit and the lowest known to overshoot — converging within eight encodes. The planner is a pure function over the list of attempts so far, and its tests pin the convergence bound and the failure mode: if even minimum quality overshoots the target, the tool reports the smallest achievable size instead of claiming success. PNG inputs are never "PNG-compressed" — a canvas cannot honestly do that — they are converted to a lossy format, labeled as such.

Resize arithmetic

Fit mode scales by min(boxWidth/w, boxHeight/h) preserving aspect ratio; exact mode stretches (with an optional lock that derives height from width); percent mode scales uniformly. Dimensions round to whole pixels with a 1-pixel floor so extreme aspect ratios cannot collapse to zero. Outputs are capped at 16,384 pixels per side and 80 megapixels overall, with a warning above 50 megapixels. Inputs are limited to 50 megapixels, 100 MB per file, and 40 files or 300 MB per selection. Enlargement is permitted but flagged: interpolation adds no detail, and the tool says so rather than advertising "enhancement".

The PDF writer

Image to PDF uses no library. A ~200-line writer assembles PDF 1.4 bytes directly: a catalog, a page tree, and per image a page object, a content stream, and the JPEG data embedded verbatim as a DCTDecode XObject — grayscale and CMYK JPEGs get the matching color space read from their own frame headers. Page geometry ("match image" at a chosen DPI, or A4/Letter with the image fit inside half-inch margins and centered) is computed by a pure function. Tests assert the header, object count, cross-reference offsets, EOF marker, and that embedded JPEG bytes round-trip byte-for-byte; the client re-checks the assembled structure before offering the download.

Verify the privacy claim yourself

"Your files never leave your browser" is enforced by architecture, and you do not have to take our word for it:

  • Open your browser's DevTools (F12) → Network tab, then convert a file. You will see no request carrying your image — no POST, no fetch, nothing but the page's own static assets.
  • The site's Content-Security-Policy header setsconnect-src 'self': the browser itself refuses to let scripts on this page send data to any other origin. Check it in DevTools → Network → the document request → Headers.
  • The site is static files — there is no server application and no upload endpoint to receive files in the first place. Downloads are object URLs pointing at memory in your own tab.

Worked examples can't drift

Numbers in page copy — the resizer's "4032×3024 fit into 1200×1200 becomes 1200×900", the PDF page's point sizes — are computed at build time by the same engine code that processes your files. If the logic changed, the copy would change with it (or the build would fail), so the documentation cannot silently disagree with the tools.

Tested against fixtures, fixed with tests

The engines are covered by an automated suite: byte-array fixtures for every format signature (including mismatched-extension and truncated cases), convergence and unreachable-target cases for the compression search, aspect-ratio edge cases for the resizer, and structural assertions for the PDF writer. If you believe an output is wrong, that is exactly the report we want — see the contact page. Confirmed issues are fixed in the engine and locked in with a new test so they cannot recur silently.