Skip to content

Instantly share code, notes, and snippets.

@quanon
Last active June 16, 2025 02:23
Show Gist options
  • Save quanon/266f96f6e984b766a81311f968a70d83 to your computer and use it in GitHub Desktop.
Save quanon/266f96f6e984b766a81311f968a70d83 to your computer and use it in GitHub Desktop.
Compress images larger than 5MB
require 'mini_magick'
require 'fileutils'
TARGET_DIR = Pathname(ARGV[0] || '.')
BACKUP_DIR = TARGET_DIR.join('backup')
IMAGE_EXT = %w(jpg jpeg png gif bmp tiff webp heic avif)
SIZE_LIMIT = 5 * 1024 * 1024 # MB
class Image
attr_reader :size, :quality
def initialize(filepath, quality: nil)
@filepath = filepath
@size = @filepath.size
@quality = quality
end
def mb
(@size / 1024.0 / 1024.0).round(2)
end
def compress!(size_limit)
image, quality = nil, nil
(1..100).bsearch do |m|
image = MiniMagick::Image.open(@filepath)
image.format('jpg')
quality = 100 - m
image.quality(quality)
image.size <= SIZE_LIMIT
end
image.write(@filepath)
Image.new(@filepath, quality: quality)
end
private
def image
@image ||= MiniMagick::Image.open(@filepath)
end
end
TARGET_DIR.glob('*').each do |filepath|
next unless filepath.file?
next unless IMAGE_EXT.include?(filepath.extname.delete('.').downcase)
next unless filepath.size >= SIZE_LIMIT
BACKUP_DIR.mkdir unless BACKUP_DIR.exist?
backup_path = BACKUP_DIR.join(File.basename(filepath))
FileUtils.cp(filepath, BACKUP_DIR.join(filepath.basename)) unless backup_path.exist?
image = Image.new(filepath)
compressed_image = image.compress!(SIZE_LIMIT)
puts("#{filepath}: #{image.mb} MB -> #{compressed_image.mb} MB")
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment