#!/usr/bin/python

# image_overlay_montage.py
#       --copyright--                   Copyright 2007 (C) Tranzoa, Co. All rights reserved.    Warranty: You're free and on your own here. This code is not necessarily up-to-date or of public quality.
#       --url--                         http://www.tranzoa.net/tzpython/
#       --email--                       pycode is the name to send to. tranzoa.com is the place to send to.
#       --bodstamps--
#       March 12, 2005          bar
#       March 18, 2005          bar     help
#       March 20, 2005          bar     tuple, numeric colors for older version of PIL
#       March 22, 2005          bar     don't do 'em big if the image size is 48 or over
#       November 18, 2007       bar     turn on doxygen
#       November 27, 2007       bar     insert boilerplate copyright
#       May 17, 2008            bar     email adr
#       --eodstamps--
##      \file
#
#
#       Crate a montage by overlaying images.
#
#


import  math
import  os
import  random
import  StringIO

import  Image

__ALL__ = [
            'make_montage_image_from_images',
          ]



WIDTH   = 64
HITE    = WIDTH


def make_montage_image_from_images(files_or_images, twidth = None, thite = None, width = None, hite = None) :

    if  width  == None  :   width  =  WIDTH
    if  hite   == None  :   hite   =  HITE
    if  twidth == None  :   twidth =  min(48, width * 3)
    if  thite  == None  :   thite  =  min(48, hite  * 3)

    twidth      = max(width, twidth)
    thite       = max(hite,  thite)

    io      = Image.new("RGBA", [ twidth, thite ], 0xffffff)
    a       = Image.new("1",    [ twidth, thite ], 0)
    io.putalpha(a)

    # io      = io.crop( ( 0, 0, twidth, thite ) )

    if  len(files_or_images) :

        #
        #       Lay the images down so that the first image in 'files_or_images' is the first to be put down, since it will de-transparent the pixels and be on top
        #
        cnt     = max(41, int(41 * math.sqrt(thite * twidth) / 100))
        for idx in range(0, cnt) :

            fn      = files_or_images[idx % len(files_or_images)]

            sio     = False
            if  (fn.find('\0') >= 0) or (not os.path.isfile(fn)) :
                fn  = StringIO.StringIO(fn)
                sio = True

            ii = Image.open(fn)
            ii = ii.convert("RGBA")

            (w, h) = ii.size

            w = min(w, twidth)
            h = min(h, thite)

            rx = random.randint(-(w / 2), twidth - (w / 2))
            ry = random.randint(-(h / 2), thite  - (h / 2))

            #
            #   Put the first image in a notable position
            #
            if  idx == 0 :
                rx                                  = (twidth * 39) / 100
                if  random.randint(0, 1) > 0 :  rx  = (twidth * 61) / 100
                rx  -= (w / 2)
                ry                                  = (thite  * 39) / 100
                if  random.randint(0, 1) > 0 :  ry  = (thite  * 61) / 100
                ry  -= (h / 2)

            iw = w
            if  rx + iw > twidth :
                iw = twidth - rx
            ih = h
            if  ry + ih > thite :
                ih = thite - ry

            x  = 0
            if  rx < 0 :
                x   = -rx
                iw +=  rx
                rx  = 0
            y  = 0
            if  ry < 0 :
                y   = -ry
                ih +=  ry
                ry  = 0


            ii  = ii.crop( ( x, y, x + iw, y + ih ) )

            box = ( rx, ry, rx + iw, ry + ih )

            ci  = io.crop(box)

            ic  = Image.composite(ci, ii, ci)

            io.paste(ic, box)

            if  sio :   fn.close()

        pass

    if  (twidth != width) or (thite != hite) :
        io = io.resize( ( width, hite ), Image.ANTIALIAS)

    return(io)





if  __name__ == '__main__' :


    import  glob
    import  sys

    import  replace_file
    import  TZCommandLineAtFile
    import  tzlib


    help_str = """
    python image_overlay_montage (options) ambiguous_input_file(s)... output_file

    Creates an image file by overlaying a gob of given images on to a large
    temporary image, and then scaling the image down to an output
    (gif/jpg/png) image.

    --thite     pixels      Set the temporary hite  (of the large image).
    --twidth    pixels      Set the temporary width (of the large iamge).
    --hite      pixels      Set the hite of the output image.
    --width     pixels      Set the width of the output image.

    """

    del(sys.argv[0])

    TZCommandLineAtFile.expand_at_sign_command_line_files(sys.argv)


    width   = None
    hite    = None

    twidth  = None
    thite   = None

    ofile_name = None


    if  tzlib.array_find(sys.argv, "--help") >= 0 :
        print help_str
        sys.exit(254)
    if  tzlib.array_find(sys.argv, "-h") >= 0 :
        print help_str
        sys.exit(254)
    if  tzlib.array_find(sys.argv, "-?") >= 0 :
        print help_str
        sys.exit(254)


    while True :
        oi  = tzlib.array_find(sys.argv, "--thite")
        if  oi < 0 :    break
        del sys.argv[oi]
        thite  = int(sys.argv.pop(oi))

    while True :
        oi  = tzlib.array_find(sys.argv, "--twidth")
        if  oi < 0 :    break
        del sys.argv[oi]
        twidth = int(sys.argv.pop(oi))

    while True :
        oi  = tzlib.array_find(sys.argv, "--hite")
        if  oi < 0 :    break
        del sys.argv[oi]
        hite   = int(sys.argv.pop(oi))

    while True :
        oi  = tzlib.array_find(sys.argv, "--width")
        if  oi < 0 :    break
        del sys.argv[oi]
        width  = int(sys.argv.pop(oi))


    if  len(sys.argv) < 2 :
        print "Please tell me (ambiguous) input file(s) and the output file!"
        sys.exit(101)


    ofile_name = sys.argv.pop(len(sys.argv) - 1)


    files       = []
    while sys.argv :
        files  += glob.glob(sys.argv.pop(0))

    files       = filter(lambda fn : fn != ofile_name, files)

    random.shuffle(files)

    #
    #   Test the direct image logic. This next statement can be commented for the subroutine to open and read the files directly, itself.
    #
    # files       = map(lambda fn : open(fn, "rb").read(), files)

    io          = make_montage_image_from_images(files, twidth = twidth, thite = thite, width = width, hite = hite)

    ( p, fn )   = os.path.split(os.path.normpath(ofile_name))
    tfile_name  = os.path.join(p, "tmp_" + fn)

    io.save(tfile_name)

    replace_file.replace_file(ofile_name, tfile_name, ofile_name + ".bak")


#
#
#
# eof

