The main bottleneck was that I was downloading the images one at a time. It worked, but it took a while.
Now I kick off all of the downloads at once, and process each image as it shows up. It's less flexible, but if everything goes well, everything is done in the time it takes for the longest picture to download, rather than the total time for all of the pictures to download...
Now I just have to figure out why, when I push the image limit over 25, it runs fine as a stand alone program, but dies when running under Roxen. I probably need to increase the size of the Roxen thread pool or something similar...