Batch resize and optimize images automatically with ruby script and tinypng/tinify API

Adding images to websites is crucial. And I found preparing images for websites hugely annoying. This is the process almost everybody should (!) go through:

  1. Find image
  2. Change file name
  3. Remove image meta data
  4. Crop to focus on most important part and get width to height ratio right
  5. Resize to web dimensions, e.g. 1600x800
  6. Optimize image, e.g., via TinyPNG or local software

Obiviously, few developers do all of these steps. I simply have neither the time nor interest, but carefully formatted images help with load times, traffic costs, and user experience.

So what do I do to resize and optimize images automatically? What every developer would do — write a script :D

I really love TinyPNG's loss-less compression, but uploading with the web-based interface, downloading and unzipping is already a bit much for me, and the web version only allows 20 images, each 5 MB max and doesn't let you resize. Luckily, they do offer an API used by 50,000 companies and developers with 500 free image compressions per months which also resizes, and is not restricted by image size or number of images. So a great tool to batch resize and optimize!

Screenshot tinypng homepage o

So just go to tinypng.com/developers to get yourself a free API key.

TinyPNG also comes with a ruby gem called tinify and an API documentation. For the script, just install the tinify gem to your system:

gem install tinify

The script I use takes all image files from the same folder as the script, resizes images to a standard 1,600x800, strips meta data (default for tinyPNG), and adds an "o" to the filename (for "optimized"). Here the script:

# tinify.rb

require 'tinify'
Tinify.key = "YOUR_API_KEY"

# Take png and jpg file names from directory and store in images array
images = []
images << Dir["#{__dir__}/*.png"]
images << Dir["#{__dir__}/*.jpg"]

images.flatten.each do |image|
  # Take source file name
  source = Tinify.from_file(image)

  # Specify resizing:
  # - 800x1,600
  # - "thumb" is an advanced implementation, focusing on object, potentially adding whitespace
  # see https://tinypng.com/developers/reference/ruby for details
  resized = source.resize(
    method: "thumb",
    height: 800,
    width: 1600
  )

  # Add "o" for optimized to output file name
  puts image_name_optimized = image.gsub(".", "_o.")

  # Resize and output to file
  resized.to_file(image_name_optimized)
end

Make sure to replace YOUR_API_KEY with your tinyPNG API key. Run it with any text editor that allows script execution, e.g., for Atom install the Script or Atom-runner packages.

Using this script, 5 MB images or screenshots come in at around 50 KB and still look great. You can for sure optimize further, but frankly, for me 50 KB for full-width images are kind of sufficient.

The workflow is as follows:

  • Put the script in a folder, e.g., "tinify"
  • Collect images to compress, and put them into the tinify folder
  • Rename the files to optimize for SEO (compare On-page SEO: Images alt-text)
  • Run the script, can take a bit of time depending on the number of files
  • Copy & paste the file names from the script's output into your source code where needed
  • Move files with "o" (optimized to your image folder)
  • Move the original files to another folder (e.g., "old"), or delete

You can of course automate some of the steps above as well, but I tried to focus on the batch optimization. Thanks to the TinyPNG-Team! Hopefully this helps someone — any suggestions for improvement?

comments powered by Disqus