###############################################################################
#
#     picturetile.pl
#
#     Takes a bunch of images and tiles them into one large image.
#     Not so much a collage, as a "photo wall."
#
#     The images are selected randomly from the given directory, and packed
#     together as tightly as possible.  Images that are very small are
#     assumed to be thumbnails and are ignored.  No image will be used more
#     than once, and the images need not be of the same size or aspect ratio.
#
#     Created: 14-Mar-2005.
#
###############################################################################
#
# Options:
#
#     --verbose        Loudness.  -vvv for more.
#     --size WxH       Max size of the resultant image.
#     --margin N       Spacing between images.  default 8 pixels.
#                      This may be negative to make the images overlap.
#     --border N       Size of the overall outside border.  Default 8 pixels.
#     --directory DIR  Directory tree where images are found.
#     --background C   Background color, default white.
#     --scale N        Resize the sub-images before pasting; default 1.0.
#     --uniform        If all your images are the same size, use this to get
#                      a more regular grid (i.e., all lines flush-left.)
#     --checkpoint     Write the output file at the end of each line, as well
#                      as at the very end (so you can watch the progress.)
#     --pages N        Instead of just writing one image file, write up to N.
#                      Does not duplicate any pictures between pages until
#                      the last page (where it may duplicate some in order
#                      to fill out the remainder.)
#     --quality PCT    Compression level when writing JPEG or PNG files.
#     --cmyk           Write CMYK instead of RGB.
#
###############################################################################
#
# Example:
#
#      Suppose you have a bunch of images from a 6 megapixel camera, and you
#      want to end up with a file that you can have printed on a 30" x 60"
#      sheet at 200 DPI, where each individual photo is snapshot-sized
#      (meaning around 5" in its longest dimension.)
#
#      The size of the output file should be 30" x 200 DPI by 60" x 200 DPI,
#      or 6000 x 12000 pixels.
#
#      Within that image, each individual photo should be 5" x 200 DPI, or
#      1000 pixels.  Since 6 megapixel images are a mixture of 3072 x 2048
#      landscape and 2048 x 3072 portrait, that means they need to be scaled
#      down by 1000/3072, or 0.3255.
#
#      If you want a half-inch border on the outside, that's .5" x 200 DPI
#      or 100 pixels.
#
#      So you'd invoke this program as:
#
#          picturetile.pl --verbose                   \
#                         --size 6000x12000           \
#                         --scale 0.3255              \
#                         --border 100                \
#                         --directory /the/pictures/  \
#                         output.jpg
#
#      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 can write a TIFF (or just about anything else) instead of a JPEG
#      by using the appropriate output file extension.
#
###############################################################################
#
# Details:
#
#     The images are packed in pretty tightly, but bin packing is NP-complete,
#     so the packing will not be optimal.  This program usually gets at least
#     75% coverage, which isn't so bad.
#
#     The traditional bin-packing algorithm is to sort the objects by size,
#     and pack them in largest to smallest ("first-fit decreasing"), but that
#     doesn't result in an aesthetically pleasing result (all the big images
#     would be clustered in one corner.)
#
#     The method used here is a Tetris-like strategy:
#
#       - place the first image at the bottom left;
#       - for each subsequent image:
#          - place it just to the right of the previous image, at the top edge;
#          - drop it straight down until it collides with another image;
#          - then move it left, if possible;
#          - then drop again, if possible.
#
#     Then the overall image is cropped to the resultant bounding box, and
#     written out.
#
#     Images are chosen randomly, and no image will be used more than once,
#     unless the supply of images is exhausted before the page is full.
#     Very small images in the source directory (thumbnails) are ignored.
#
# Warning:
#
#     When dealing with very large images, make sure you have plenty of free
#     space in your /tmp directory (or point $TMPDIR at somewhere spacious).
#     The ImageMagick library sometimes silently fails when it runs out of
#     room for its scratch files.
#
###############################################################################
#
# Alternatives:
#
#     If all your images are exactly the same size, or if you want them
#     arranged on a regular grid, then the ImageMagick "montage" program
#     will probably serve you better than this script.
#
###############################################################################
#
# Discussion:
#     http://jwz.livejournal.com/455804.html
#
###############################################################################

