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 named photo.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.

The conversion pipeline

Decoding uses the browser's own codecs via createImageBitmap with imageOrientation: '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. 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.

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. The site publishes no compression percentages anywhere, because no percentage is true for every image.

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 (browser canvas limits) and warned above 50 megapixels. 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 sets connect-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.