Saturday, April 19, 2008

ImageMagick Bulk Image convert Fun

ImageMagick can do an amazing number of command line manipulation functions. ImageMagick's convert command, for example, can convert an image from one format to another and do a bunch of transformations along the way. Recently I needed to convert a whole bunch of SVG files deeply nested in a directory structure into transparent PNGs. convert, combined with a little bash magick, makes this a quick and painless task:

find . -name "*.svg" -exec sh -c 'convert -transparent white ${1} ${1%\.svg}.png' - {} \;
view raw gistfile1.sh hosted with ❤ by GitHub


Let's break that down.


  1. Recursively find every file ending in .svg and pass each one separately to exec

  2. For each exec invoke a shell that executes a command from the given string with the filename getting passed as ${1}

  3. In the command call convert, changing white in the SVG to transparent in the PNG where the first argument is the SVG to convert, and the second argument is the destination PNG filename



Job complete.

Massage Rails better_nested_set full_set into a hierarchy - XML

In a previous post I showed how to convert a betternestedset full_set into a JSON hierarchy that you might feed to a javascript or flash component. Another thing you might want to do is to massage the data into an XML hierarchy to feed a ... javascript or flash component. Now you could use similar code to the previous example and build the XML document up with REXML or another XML library and be done with it. You may, however, want to avoid using such an XML library to avoid the speed penalty that comes with it. Here is an example of converting the content returned from full_set into an XML document without using an XML library:

def full_xml
the_full_set = full_set
ancestry = [build_node(the_full_set.shift)]
xml = ancestry.first[:xml]
while !the_full_set.empty?
next_node = build_node(the_full_set.shift)
if next_node[:level] < ancestry.last[:level]
while next_node[:level] < ancestry.last[:level]
popped_node = ancestry.pop
xml << '</node>' if !popped_node[:closed]
end
xml << next_node[:xml]
elsif next_node[:level] == ancestry.last[:level]
xml << "</node>#{next_node[:xml]}"
ancestry.last[:closed] = true
else
xml << next_node[:xml]
end
ancestry << next_node
end
while !ancestry.empty?
next_node = ancestry.pop
xml << '</node>' if !next_node[:closed]
end
xml
end
def build_node(message)
{:xml => "<node label=\"#{message.subject}\">",
:level => message.level}
end
view raw gistfile1.rb hosted with ❤ by GitHub