Quick & Dirty Image Resizer with Ruby and RMagick

Aug 02

I needed to resize a folder of images the other day. So I wrote this handy script:

Update (08/10/12) — I had a conversation about shaders and threading with a SIGGRAPH attendee on a flight from LA back home. As a result of that conversation I’ve decided to multi-thread this script in an effort to make it faster. In the process I beat the crap out of my MacBook Pro but it took the beating like a champ. Thankfully this made me realize that the Ruby garbage collection wasn’t working fast enough. So I added some code to free the image resources when they were no longer being used. This had an added benefit of speeding things up even more. I found the Parallel gem which made the multi-threading part of it insanely easy. See for yourself below.

#!/usr/bin/ruby

require "RMagick" # image processing wrapper for ImageMagick
require "Parallel" # https://github.com/grosser/parallel

# ensure dirs are available for writing
["thumbs","full","processed"].each do |dir|
  unless File.directory? dir
    puts "Creating #{dir}/"
    Dir.mkdir dir
  end
end

# encapsulates the image resizing logic
def resizeImage(f)

  # get the first frame of the image (JPGs usually have only one)
  img = Magick::Image.read(f).first
  # prep thumb and full sizes
  thumb = img.resize_to_fit(100, 100)
  full = img.resize_to_fit(580, 580)
  # write resized images
  thumb.write("thumbs/#{f}") {self.quality = 60}
  full.write("full/#{f}") {self.quality = 75}

  # free up RAM
  img.destroy!
  thumb.destroy!
  full.destroy!

end

# Loop through items in the dir
files = Dir.entries "."
# clean file list of known non-files
files.delete_if {|f| [".", "..", ".DS_Store"].index(f) != nil or Dir.directory?(f) }

# let the user know we've begun...
puts ("Resizing #{totalFiles} files...")

# process the images in parallel threads (up to 4)
completed = Parallel.each(files){|file|
  if File.file? file
    resizeImage(file)

    # move the file to processed folder
    system("mv \"#{file}\" processed/")

    # micro-sleep so other processes can get some CPU time
    sleep 0.3
  end
}

# Show a growl notification if available.
system("growlnotify --appIcon Terminal -m 'Finshed resizing images!' Ruby")

puts "Finished resizing #{completed.length} images"

The script uses the multi-process threading model which allows the Parallel gem to spawn a process for every native thread available on each processing core of the machine it’s running on. With my early 2012 MBP with an Intel Core i7 quad-core CPU that means 8 threads at once. That’s an increase of 800% from what the original script could do. I highly recommend this gem for your simple parallel processing needs. I suppose you might not need the micro-sleep in the worker block if you ran the script through nice but I find that it doesn’t affect the speed too much as-is.

more…

 

IEnumerable Extensions (.NET)

Feb 01

I’m starting to really enjoy working with C# and LINQ with ASP.NET. I particularly enjoy the IEnumerable extensions which are added by LINQ. I never gave LINQ much credit before. That is probably because I viewed it as a way to allow developers to get away with not knowing SQL. Now that I’ve had the chance to put it into action I realize that it makes .NET feel a lot like Ruby and Rails. And I like the feel of Ruby. So now I’m beginning to like the feel of C#.NET. I wish I had arrived at this point sooner. Code pr0n to follow below.

The code below is used to convert a business object into a Dictionary suitable for use in binding to a ListControl object. more…

 

Hacked.

Dec 27

THIS IS STILL ONGOING! Resolved.

So, somehow someone was able to gain enough access to my hosting system that they were able to change read-only .htaccess files in my account. I’m not sure if that was something caused by elevated permissions on my shared server or if someone was able to exploit my content management system. (WordPress) It seems like it make have been the latter as the “infection” ceased when I upgraded WordPress and deleted the cache. It is possible the infection could have been via an exploit in the caching subsystem. I’ll have to look into it further some other time. See update below.

This is what the “infection” looks like. The malicious code prepends and appends some stuff to your .htaccess files in all folders in the user’s home dir where an .htaccess already exists. It does not seem to attempt to create new .htaccess files. more…

 

Updated Adium Spotify Xtra

Nov 08

I have made some improvements to the Adium Spotify Now Playing Xtra.

I added a fast-fail when the application isn’t running. If for some reason any errors occur the script will return an empty string. I also added the HTTP link to the current track. You can find my version of the plugin linked via a comment on the Adium Xtras page.

Download Now.

 

My Custom Demandware UX Studio Icon for OSX

Oct 04

I am so super impressed with Demandware at this point. I haven’t seen much but I like how everything fits together. The only thing that didn’t fit – on my Mac at least – was the icon for the IDE. (A plugin library on top of Eclipse) So I remedied that situation:

Demandware Logo Inspired Icon for Demandware UX Studio

My Demandware logo inspired icon for Demandware UX Studio

Now to set the app’s icon in the two places that matter. more…