Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ByteFit

Choose the bytes, not the format.

ByteFit finds the best useful JPEG, PNG, or WebP image that stays under an exact file-size limit.

See it work

The same 7479×11146 Mona Lisa source was fitted to two very different budgets:

Mona Lisa original, 8 MB ByteFit output, and 216 KiB ByteFit output shown as full images and matched detail crops

The full views show the overall result; the matched crops expose what each byte budget does to fine detail. They use the same region and display size for an honest visual comparison.

Version Exact bytes Dimensions Reduction Open image
Original source 94,310,471 7479×11146 Preview
8 MB ceiling 7,919,622 7479×11146 91.6% Full output
216 KiB ceiling 178,080 2992×4458 99.8% Full output

The comparison card was rendered from the actual 94 MB source and the two real ByteFit outputs. The repository keeps only a lightweight preview of the original to avoid adding 94 MB to its history. The artwork is Leonardo da Vinci's public-domain Mona Lisa.

bytefit fit mona-lisa-original.jpg --max 8MB \
  --output mona-lisa-8mb.jpg

bytefit fit mona-lisa-original.jpg --max 216KiB \
  --min-width 2900 --output mona-lisa-216kb.jpg

The second result is below rather than exactly at 216 KiB because JPEG has discrete quality settings. ByteFit treats the limit as a ceiling and never rounds up to a candidate that is even one byte too large.

Install

ByteFit requires Python 3.11 or newer.

python -m pip install -e .

Use

# Let ByteFit choose the output format.
bytefit fit photo.jpg --max 500KiB

# A supplied extension limits the search to that format.
bytefit fit photo.jpg --max 2MB --output fitted.webp

# Keep an audit report containing every encoded attempt.
bytefit fit photo.jpg --max 500KB --json report.json

# Inspect an input without changing it.
bytefit inspect photo.jpg

Useful controls:

  • --profile universal-image restricts output to conservative JPEG/PNG support.
  • --format jpeg,webp explicitly limits candidate formats.
  • --min-width 1280 and --min-height 720 prevent unusably small results.
  • --flatten '#ffffff' deliberately removes transparency against a color.
  • --effort quick|balanced|max changes search breadth, never the hard limit.
  • --force intentionally replaces an existing output; the default is no-clobber.

KB and MB are decimal units. KiB and MiB are binary units, so 500KB means 500,000 bytes while 500KiB means 512,000 bytes.

What ByteFit actually does

  1. Normalizes orientation, color, transparency, metadata, and profile rules.
  2. Searches allowed formats, useful resolutions, and real encoder quality levels.
  3. Counts exact encoded bytes, rejects hard-rule violations, measures fitting candidates, and atomically writes the best one.

For large images, the search uses size-only probes, interpolation around the budget boundary, reduced metric decodes, and an early full-resolution win path. The 94 MB example above takes five JPEG probes on the balanced path instead of blindly trying every quality, resolution, and format.

The quality score combines pixel similarity, edge retention, retained resolution, and verified properties. It is a transparent selection rule—not a claim that a single number captures human perception. See The math behind ByteFit for the equations, search method, guarantees, and worked example.

Test

PYTHONPATH=src python -m unittest discover -s tests -v

The test suite uses generated images and checks real codec round trips, exact size parsing, format-limited searches, transparency, impossible budgets, quality selection, atomic output, profiles, and JSON reports.

Current scope

ByteFit handles one still JPEG, PNG, or WebP image per command. Animated images, AVIF, video, and semantic/perceptual models are not supported yet.

MIT licensed.

About

Fit images into your desired size limit!

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages