Today's hack: picturetile.pl.

Back when I used a film camera, I used to cover one of my walls with snapshots. They currently cover an area of about 10' wide and 8' high, but I haven't updated them in a few years, because I don't use film any more.

And then a few weeks ago, this post about how to use iPhoto to make a poster out of a grid of digital photos was making the rounds, and that inspired me to write my own.

The thing I didn't like about that iPhoto technique is that it required all the photos to be the same shape (all portrait or all landscape) and, well, I have both. So I wrote this program to do a more chaotically-packed layout of photos of arbitrary sizes (sample output to the right; instructions at the top of the file.)

I haven't tried actually printing one of these yet. Should I just go to Kinko's?

The Perl interface to ImageMagick is pretty slick! I hadn't taken notice of it before.

What I originally wanted to do was, instead of writing out a single flat file with the images in them in the randomly-chosen layout, write out a file with each image on its own layer, positioned properly. That way I could easily go in and hand-tune the layout by just dragging the layers around in GIMP. But, it seems that TIFF files don't store position info for the layers (they all start at 0,0) and I can't find any other multi-layered image format that can be both written by ImageMagick and read by GIMP. So, so much for that idea.

I suppose could have accomplished this by writing this program in Script-Fu (GIMP's Scheme-ish extension language) instead of in Perl, but there's just something about Script-Fu that rubs me the wrong way, so I didn't bother learning it.

Another thing that's going to be problematic about using this (for me, anyway) is that, while I've saved the original, high resolution version of nearly every photo I've taken, the versions that I have color-corrected and put in galleries are all the small versions. This means that I'll either have to re-color-correct the big originals, or just print out the uncorrected versions. Maybe I should add an option to the script to do "auto-levels" on the images as it imports them. That will crappify certain pictures, but will probably improve most of them...

Tags: ,

44 Responses:

  1. unify says:

    Write a script to scale the high resolution original down to the gallery size, fiddle with the levels until they match, and apply those levels to the original.

  2. aris1234 says:

    The guys at Lumapix do some pretty impressive windoze software to do something similar. Ok, it's not FREE - but impressive still.

  3. nothings says:

    I can't find any other multi-layered image format that can be both written by ImageMagick and read by GIMP

    I have neither software to test, but I see that both claim to support Photoshop's PSD format, which does layers. Perhaps they do not sufficiently overlap in their support.

  4. geektalk says:

    There is a GIMP-Perl interface; you don't have to use the Scheme deal. The perl interface is very OO-y. Maybe you've looked at it and decided it sucks, too? I used it a bit to create some web galleries and found it to be pretty straightforward.

    Then you can write .xcf files or whatever gimp's native format is called.

  5. pir_anha says:

    nifty. this might just replace my tack-em-up-one-by-one method (i still print even though i no longer use much film).

    TIFF files do store layer offsets; this must be a GIMP problem (i seem to recall reading recently something about this not working correctly), so there's hope on the horizon for solving your problem the way you want.

    and just a note on workflow: i've taken to colour-correct and generally clean up the high-res originals before reducing size and publishing, since i ran into a similar problem a while ago, and no automatic treatment did the job. auto-levels suck IMO; i generally use curves instead of levels anyway (but auto-curves suck too). might as well bite into the sour apple of redoing the corrections on your high-res images; in the long run you might be happier with that.

    • rzr_grl says:

      and just a note on workflow: i've taken to colour-correct and generally clean up the high-res originals before reducing size and publishing

      I've been learning this the hard way too, lately. Each contest/internship/scholarship/etc. wants my portfolio images in a different resolution. Recently, I've had to go through and correct them all several times - once for a 10% difference in size!

      I finally wised up, and my workflow is this: pull in all the jpgs; edit; color-correct, crop and clean up the selects and save them as tiff; resize and unsharp mask; and save them as small jpgs. This way the original file is intact, and I can get new, correct versions in any size with a simple resize + unsharp mask batch process.

  6. jaykayess says:

    I used to use ImageMagick, but the API drove me nuts. Some things are documented, other's aren't; some things ARE except that they just plain don't work. It's also a pain to compile.

    So now I use Imager: http://search.cpan.org/~tonyc/Imager-0.44/Imager.pm

    And here's what comes out: http://www.flickr.com/photos/jaykayess/sets/83361/

    • citizenx says:

      My personal favorite is when I had to use a value of 'true' to get something to work correctly. I really enjoy it when true/false gets corrupted into stupidity.

    • jwz says:

      Very nice collage effect! How are you combining the images? (Thinking of adapting that for webcollage, obviously...)

    • endico says:

      What a great collage. I just did something like this in photoshop, but only one of them. I'm not cool enough yet to have a script to generate them automatically.

  7. nester says:

    I tried this on my personal colocation machine.. it's a dual 733mhz PIII with 512mb ram.. but I think I'm slowly losing my hard drive. hard writes to the drive causes the load to spike..

    Of course, that never stops me from trying.. :) Yeah, spiked to load average 10 before I had to kill it..

    Put it on a Xeon box that's largely idle did 62 pics (2.1 megapixel each) in ~33 seconds..

    Looks neat. :)

  8. zuvembi says:

    In the past month I've been thinking about doing this exact thing. I hadn't gotten around to actually doing anything about it yet, so this is awesome. I will have to fiddle around with this this weekend (too busy painting this week to muck with it till then). Thanks.

    You might try Shutterfly for printing that out as a poster. They have a 20" x 30" print as one of their standard options, which might be large enough for you. They do good processing (at least I have been happy with my results from them). They also have a linux client for upload which works reasonably well. I'd rather use FTP or something, but at least when I was uploading my friends 700 megs of images I didn't have to point and drool all of them through a browser upload form.

    They also have a pretty fast turnaround on orders. I ordered some prints on a Monday night and got them delivered (to Seattle) by Thursday. Their processing center is in California, so it might even be faster for you.

  9. yawns says:

    The perlmagick Equalize function might be what you want.

    See : http://openphoto.net/gallery/image.html?image_id=6847

    Then select 'Equalize' from the 'Apply Filter' menu for an example.

    What we need more than anything is a good, perlmagick image mosaic program.

    The few unix imagemosaic tools i've found tend to puke when dealing with a relatively low number of images, and you need a large pallette to output really quality mosaics....



    • parkrrrr says:

      I'm assuming you've tried Metapixel. I think you'll find that "you need a large palette to output really quality mosaics" is more of a property of the form than a limitation of the specific implementations, unless you cheat and tweak the hue on your subimages (as I've seen done on at least one "professional" mosaic; I think it was the poster for The Truman Show.)

      • yawns says:

        I've tried it in the past and had some issues with it.

        I dont think i've tried the latest release, maybe i need to give
        it another shot..



  10. hub_ says:

    That suck, ImageMagick does not write GIMP .xcf format. Otherwise I think you would be able to do it.

    Maybe compositing in SVG ?

  11. luserspaz says:

    I hacked around with your script a bit to make it produce html, with absolutely positioned images. It works, except I then realized that I don't know how to turn that into an image. Printing to PDF would be logical, except I don't know how to set the paper size correctly.

    I was thinking that you could use some javascript to drag the images around, and then print it like that. Of course, you can't save your positioning then, and you can't scale your view of the whole thing (at least not in Mozilla).

    Oh well.

  12. flipzagging says:

    This isn't much help to you, but I wrote something similar that uses a really crappy physics-based model. It takes a few minutes, but you get something like this.

    The pipeline is totally idiosyncratic. Maybe I can abstract out the layout part if you're interested. Catch me this week as I'm unemployed.

    This was part of a semi-abandoned project to make images that represent the content of blog posts. Confession: I used some of your postings as sample texts.

    • jwz says:

      I like that layout. I'd like to hear at least a description of the algorithm. I guess my technique is more "tetris-based" than "physics-based". (See, all those tetris hours I logged turned out to be useful after all.)

      • flipzagging says:

        Here's an animation I made when I was debugging it.

        My program has to deal with images of greatly varying sizes so it probably isn't much use for you. It works like this:

        position all images on an infinite hyperbolic bowl, the
        largest ones at the center, the small ones further out.

        while (boxes are still moving significantly)

        apply gravity vector to all boxes
        (they slide down the sides of the hyperbolic bowl)

        for each combination of boxes:

        if any box is overlapping,

        move them apart so they don't overlap

        perform 1-d vector collision (m1v1 = m2v2) on the vectors
        perpendicular to the edge that was most overlapping

        accelerate every box (forces --> velocity)
        move every box (velocity --> position)

        apply friction to every box (velocity *= 0.005)

        Physics are a lot simpler when the only objects are rectangles that can't rotate. Every collision is just 1-d.

  13. past_tense says:

    # That will make use of around 80 images from that directory, and will
    # take about five minutes on a 2GHz machine. It will also use a truly
    # gargantuan amount of RAM, and result in an output file of 4-5 MB.

    "You know I've always liked that word gargantuan? I so rarely have an opportunity to use it in a sentence."

    -Elle Driver, "Kill Bill"

  14. goatbar says:

    I'm not a perl guy. Can someone clue me into what I am doing wrong?

    ./picturetile.pl --size 1000x2000 --directory images output.jpg
    *** malloc[24703]: error for object 0x1: Pointer being reallocated was not allocated
    *** malloc[24703]: Deallocation of a pointer not malloced: 0x1; This could be a double free(), or free() called with the middle of an allocated block; Try setting environment variable MallocHelp to see tools to help debug
    Image::Magick: unable to allocate string `1000x2000'.

    Mac OSX 10.3.8
    fink imagemagic 6.1.8-1
    perlmagick-pm581 5.5.6-11
    /usr/bin/perl --version

    This is perl, v5.8.1-RC3 built for darwin-thread-multi-2level
    (with 1 registered patch, see perl -V for more detail)


    • jwz says:

      Ugh. That sounds like a bug in the C side of the Perl ImageMagick library... Something's corrupting memory.

      • luserspaz says:

        FWIW, I managed to run it on Windows using ActiveState Perl, reading the images off of a network fileshare. I did have to comment out the duplicate inode check though, since all the inodes were coming out zero. Not sure if that's a Windows or an smb deficiency.

  15. anaisdjuna says:

    Cool post! Thanks for sharing your program :-)

  16. giantlaser says:

    Damn, hasn't someone made a perl script to translate perl to Script-Fu? :)

  17. spikenheimer says:

    you should have it output to the rasterbator for giant wall posters.

    • jwz says:

      I've done that kind of thing before, and getting the registration right is a real bitch.

      • spikenheimer says:

        actually the more i think about this, the less necessary it is. you're putting all the images together at full resolution, not blowing a smaller image up to gargantuan size like the rasterbator. and halftoning the output that picturetile.pl does would be silly.

        so rescind that comment o mine!

  18. jgotts says:

    If you're going for a natural effect, some of the images should be at a slight angle, perhaps up to a few degrees.

  19. zuvembi says:

    Just a note to say thanks for making this.

    I looked at this when you first wrote it, and kept intending to use it for myself. But I never got around to putting family pictures up on the wall with it.

    Earlier this month after the Obama win, I saw a link to foreign and domestic newspaper front pages after the election. One of my friends was a tireless and early campaigner for him and I thought she'd really like something to remember it by. I used picturetile to create a 20x30" poster with about 80 of the papers jammed in it. It turned out really well.

    Also in other news of how this November keeps giving: You've probably already heard this, but: Ann Coulter's jaw was wired shut.

  20. hellocatfood says:

    I've installed the picture tile plugin for f-spot, which requires that I have your script install. I've downloaded it, but where should I install it so that f-spot knows where it is?