#! /usr/bin/python2.4

import sys
import random
import Image
import math

from pic import Pic
#show, save, getPixel

DEBUG = 0

# prototype format:
# (x, y, color, count assoc)
XINDEX = 0
YINDEX = 1
COLORINDEX = 2
COUNTINDEX = 3

f=open('images\\test.log', 'w')

def setupPic(fileName):
#    im = Pic("C:\\prog\\image\\images\\"+fileName+".bmp")
    im = Pic("images\\"+fileName+".bmp")
    if DEBUG > 1:
        print "got pic"
    return im


def grayIt(picName):
    kiwi = setupPic(picName)
    kiwi.gray("images\\"+picName+"bw.bmp")



def getSamples(im):
    toRet = []
    for i in range(im.width):
        for j in range(im.height):
            newSample = [i/float(im.width), j/float(im.height), im.getPixel(i, j)/256.0]
            toRet.append(newSample)
    return toRet

def dist(xvec, yvec):
    if len(xvec) != len(yvec):
        print "ERROR (dist): two vectors do not have same dim"
        sys.exit(1)
    sum = 0
    for i in range(len(xvec)):
        sum = sum + math.pow(xvec[i]-yvec[i], 2.0)
    return math.sqrt(sum)

def computeOneY(samp, proto):
    sum = 0
    for i in range(2):
        sum = sum + math.pow(samp[i]-proto[i], 2.0)
    sum = sum + math.pow(samp[i]-proto[i], 3.0)
    return math.sqrt(sum)
    
        
        
def computeYsForSamp(samp, protos):
    toRet = []
    for i in range(len(protos)):
        toRet.append(dist(samp, protos[i][:3]))
    return toRet

def processSamp(samp, protos, tol):
    if len(protos) > 0:
        ys = computeYsForSamp(samp, protos)
        miny = min(ys)
        mindex = ys.index(miny)
        if DEBUG > 1:
            print "samp:  %s, minDist:  %s, closest:  %s" \
                  % (samp, miny, protos[mindex])
        if miny < tol:
            winproto = protos[mindex]
            newcount = winproto[COUNTINDEX]+1.0
            newx = samp[XINDEX] / newcount \
                    + (winproto[XINDEX]*(newcount-1))/newcount
            newy = samp[YINDEX] / newcount \
                    + (winproto[YINDEX]*(newcount-1))/newcount
            newcolor = samp[COLORINDEX] / newcount \
                    + (winproto[COLORINDEX]*(newcount-1))/newcount
            protos[mindex] = [newx, newy, newcolor, newcount]
        else:
            if DEBUG > 0:
                print "adding proto:  %s, dist:  %s"  % (samp, miny)
            newproto = samp[:]
            newproto.append(1.0)
            protos.append(newproto)
    else:
        if DEBUG > 0:
            print "First Proto:  %s"  % (samp)
        newproto = samp[:]
        newproto.append(1.0)
        protos.append(newproto)
    return protos

def runSamples(samps, protos, tol):
    for samp in samps:
        protos = processSamp(samp, protos, tol)
    return protos

def getNearestColor(x, y, protos):
    dists = []
    for proto in protos:
        newdist = dist([x, y], proto[:2])
        dists.append(newdist)
    mindist = min(dists)
    mindex = dists.index(mindist)
    winner = protos[mindex]
    color = winner[2]
    return color

def see(xdim, ydim, protos):
    toWrite = Image.new("L", (xdim, ydim), 256)
    for i in range(xdim):
        for j in range(ydim):
            toWrite.putpixel((i, j), getNearestColor(i/float(xdim), j/float(ydim), protos)*256)
    return toWrite

def sortByCount(x, y):
    return int(x[3] - y[3])

def thinOutProtos(protos, survivalRate):
    if len(protos) > 0:
        protos.sort(sortByCount)
        return protos[:max(1, int(len(protos)*survivalRate))]
    else:
        return []

def savePici(picName, protos, tol, num, i):
    a = "images\\art\\"+picName+"-tol%03d-clus%04d-%04d.bmp" % \
        (tol*1000, num, i)
#    b = "images\\art\\movies\\"+picName+"ind%04d.bmp" % i
    c = "%04d\t" % num
    f.write(c) 
    asdf = see(48, 48, protos)
    asdf.save(a)
#    asdf.save(b)

def runPic(picname, tol, i):
    print "--------Testing on %s--------" % picname
    im = setupPic(picname)
    samps = getSamples(im)
    protos = runSamples(samps, [], tol)
    num = len(protos)
    print " results:  tolerance:  %s, number of protos: %s" % (tol, num)
    savePici(picname, protos, tol, num, i)
    

#li = ["big"]
#for ele in li:
#    grayIt(ele)
#sys.exit(1)


#tests = ["stripes", "a", "cross", "target", "diag", "dots", "circle", "dude", "rabbitbw", "blocksbw", "tractorbw", "ricebw", "thinkbw", "ghostbw"]
tests = ["bigbw"]
#tols = [.5, .475, .45, .425, .4, .375, .35, .325, .3, .275, .25, .225, .2, .175, .15, .125, .1, .075, .05, .025]
#tols = [.025, .05, .075, .1, .15, .2, .25, .3, .35, .4, .45, .5]
tols = [.5, .4, .3, .2, .1, .05]
for test in tests:
    f.write(test+"\t")
    for i in range(len(tols)):
        print "test%s, tol%s" % (test, tols[i])
        tol = tols[i]
        runPic(test, tol, i)
    f.write("\n")

f.close()

#def randim():
#    toWrite = Image.new("L", (48, 48), 256)
#    for i in range(48):
#        for j in range(48):
#            toWrite.putpixel((i, j), random.random()*256)
#    a = "C:\\prog\\image\\images\\art\\rand.bmp" 
#    toWrite.save(a)
#
#randim()

