Skip to content

Image Compressor — Ruby source

Shrink image file sizes entirely in your browser — fixed quality or an automatic fit to a size budget, optional max-dimension resize, batch support. Nothing uploads.

This is the Ruby implementation — the same logic the interactive tool runs, in a shareable, citable form.

# Image compressor: quality search to a size budget — Ruby port of the
# image-compressor tool. Ruby's stdlib has no image codec; the encoder is a
# stand-in sized like a real one (plug in libvips: Vips::Image#webpsave :Q,
# or minimagick). The binary search is the portable part.

# Stand-in for canvas -> WebP/JPEG encode: encoded size at a quality.
encode_size = ->(q) { (12_000 + 88_000 * q).to_i } # ~100 KB at q = 1.0

# Binary-search the quality until the encoded image fits the budget
# (target_kb * 1024) — the core of the TS compressToBudget. Returns the best
# fitting quality, or nil when nothing fits (the TS fallback then re-encodes
# once at the 0.05 floor).
compress_to_budget = lambda do |encode, target_kb|
  budget = target_kb * 1024
  lo = 0.05
  hi = 0.95
  best = nil
  while lo <= hi
    mid = (lo + hi) / 2.0
    if encode.call(mid) <= budget
      best = mid          # fits — try a higher quality
      lo = mid + 0.05
    else
      hi = mid - 0.05     # too big — step down
    end
  end
  best
end

# The live tool decodes the bitmap, draws it to a canvas, then searches.
# 50 KB budget: a mid-range quality fits just under it.
q = compress_to_budget.call(encode_size, 50)
if q.nil?
  puts 'no quality fits — falling back to the 0.05 floor'
  exit 1
end
puts format('best quality %.3f -> %d bytes', q, encode_size.call(q))

Also available in 8 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 →