from JascApp import *

def ScriptProperties():
    return {
        'Author': 'Victor Reijs',
        'Copyright': '2005',
        'Description': 'Optimization with color scale',
        'Host': 'Paint Shop Pro',
        'Host Version': '8.10'
        }

import math
import sys
import sitecustomize
from scipy import *
from scipy.optimize import fmin_bfgs
import _winreg
import Image
import ImageWin
import os.path



version=0.6
numberprimcolors=3
#threshold is the RGB color step that can be perceived by eye
threshold=2.8
primkleur=['red','green','blue']
gamma=0
yearkeuze=''
cardkeuze=''
numbercolors=0

#####################
#ifrao standard scale
#####################
numbercolorsifrao=8
rowcardifrao=3
patchifrao=['black','white','grey','darkgrey','blue','green','yellow','red']
BWrangeifrao=[0,3,2,1]

#specific target values
ifrao1994srgb=[[47,46,47],[238,233,232],[116,114,114],[62,65,61],[65,62,116],[0,144,75],[245,211,0],[207,65,60]]
ifrao2001srgb=[[35,35,38],[235,234,240],[124,122,121],[63,65,65],[81,79,129],[0,150,82],[237,216,20],[194,67,53]]
ifrao1994Adobe=[[50,50,51],[236,233,231],[115,114,113],[65,67,64],[66,64,114],[77,142,80],[235,210,43],[179,67,62]]
ifrao2001Adobe=[[40,40,42],[234,233,240],[123,121,120],[66,67,67],[82,80,127],[84,148,87],[230,214,56],[169,68,56]]

#data of bminfra_1.bmp file
bmifrao1bmp=[(41, 37, 33),(228, 226, 222), (107, 97, 92),(63, 56, 53),   (81, 64, 107), (107, 131, 82), (236, 207, 71), (158, 58, 42)]
gbbmifrao1bmp=[0.44,0.50,0.51]
colormatrixbmifrao1bmp=[2,-0.01,0.06,-1.06,1.11,-0.22,0.08,-0.09,1.25]


#####################
#ifrao macro standard scale
#####################
numbercolorsifraomacro=6
rowcardifraomacro=2
patchifraomacro=['white','black','red','yellow','green','blue']
BWrangeifraomacro=[1,0]

#specific target values
ifraomacro1994srgb=[[238,233,232],[47,46,47],[207,65,60],[245,211,0],[0,144,75],[65,62,116]]
ifraomacro2001srgb=[[235,234,240],[35,35,38],[194,67,53],[237,216,20],[0,150,82],[81,79,129]]
ifraomacro1994Adobe=[[236,233,231],[50,50,51],[179,67,62],[235,210,43],[77,142,80],[66,64,114]]
ifraomacro2001Adobe=[[234,233,240],[40,40,42],[169,68,56],[230,214,56],[84,148,87],[82,80,127]]

#####################
#pietje macro standard scale
#####################
numbercolorspietjemacro=6
rowcardpietjemacro=2
patchpietjemacro=['white','black','red','green','yellow','blue']
BWrangepietjemacro=[1,0]

#specific target values
pietjemacro2005srgb=[[238,233,232],[47,46,47],[207,65,60],[0,144,75],[245,211,0],[65,62,116]]
pietjemacro2005Adobe=[[236,233,231],[50,50,51],[179,67,62],[77,142,80],[235,210,43],[66,64,114]]


#####################
#Macbeth colorchecker card 
#####################
numbercolorsmacbeth=24
rowcardmacbeth=4
patchmacbeth=['dark skin','light skin','blue sky','foliage','blue flower','blueish green','orange','purplish blue','moderate red','purple','yellow green','orange yellow','blue','green','red','yellow','magenta','cyan','white','neutral 8','neutral 6.5','neatral 5','neatral 3.5','black']
BWrangemacbeth=[23,22,21,20,19,18]

macbethsrgb=[(115,80,64), (195,151,130), (94,123,156), (88,108,65), (130,129,177), (100,190,171), (217,122,37), (72,91,165), (194,84,98), (91,59,107), (160,188,60), (230,163,42), (46,60,153), (71,150,69), (177,44,56), (238,200,27), (187,82,148), (0,135,166), (243,242,237), (201,201,201), (161,161,161), (122,122,121), (83,83,83), (50,49,50)]
macbethAdobe=[(106,81,67), (182,149,130), (103,122,154), (95,108,69), (129,128,174), (133,189,170), (194,121,48), (79,91,162), (170,85,97), (84,62,105), (167,186,73), (213,162,57), (54,62,149), (101,148,76), (152,48,58), (228,199,55), (164,83,144), (63,134,163), (242,241,236), (200,200,199), (159,160,159), (122,121,120), (84,84,84), (53,53,53)]


#####################
#pietje color scale 
#####################
numbercolorspietje=16
rowcardpietje=4
patchpietje=['light yellow','darkgrey','white','black','dark blue','yellow','yellow green','skin','grey','green','purple','light blue','blue','blue flower','red','light purple']
bwspietje=4
BWrangepietje=[3,1,8,2]


#specific target values
pietje2005srgb=[(228, 228, 111), (151, 151, 151), (248, 248, 248), (28, 28, 28), (28, 28, 248), (249, 248, 28), (111, 228, 111), (228, 111, 111), (206, 206, 206), (28, 148, 28), (248, 28, 248), (111, 228, 228), (29, 244, 244), (111, 1111, 228), (248, 28, 28), (228, 111, 228)]

pietje2005Adobe=[(203, 190, 123), (137, 141, 149), (213, 225, 231), (29, 22, 25), (8, 97, 179), (226, 200, 86), (126, 189, 131), (205, 102, 110), (175, 177, 181), (101, 177, 102), (199, 77, 143), (122, 205, 223), (106, 204, 223), (85, 130, 197), (230, 33, 27), (196, 111, 169)]



#init values for optimiation
gb=[0.45455,0.45455,0.45455]
ge=[2.2,2.2,2.2]
colormatrix=[1.,0.,0.,0.,1.,0.,0.,0.,1.]



def measure(Environment,x,y,dropper):
#put eyedropper at correct location and with correct size
    App.Do( Environment, 'Eyedropper', {
            'Point': (x,y), 
            'SampleSize': dropper, 
            'Material': App.Constants.MaterialRef.Foreground, 
            'ActiveLayerOnly': App.Constants.Boolean.false, 
            'GeneralSettings': {
                'ExecutionMode': App.Constants.ExecutionMode.Silent, 
                'AutoActionMode': App.Constants.AutoActionMode.Match
                }
            })
#measure color at positon of eye dropper
    Material = App.Do( Environment, 'GetMaterial', {
          'IsPrimary': App.Constants.Boolean.true,
         'GeneralSettings': {
                'ExecutionMode': App.Constants.ExecutionMode.Silent, 
                'AutoActionMode': App.Constants.AutoActionMode.Match
                }})
#put a black square on the patch that has been measured                
    App.Do( Environment, 'PaintBrush', {
            'BrushTip': {
                'BrushVariance': {
                    'SizeVariance': App.Constants.VarianceMethod.None, 
                    'SizeJitter': 0, 
                    'OpacityVariance': App.Constants.VarianceMethod.None, 
                    'OpacityJitter': 0, 
                    'DensityVariance': App.Constants.VarianceMethod.None, 
                    'DensityJitter': 0, 
                    'RotationVariance': App.Constants.VarianceMethod.None, 
                    'RotationJitter': 0, 
                    'ThicknessVariance': App.Constants.VarianceMethod.None, 
                    'ThicknessJitter': 0, 
                    'FadeRate': 100, 
                    'ColorBlendVariance': App.Constants.VarianceMethod.None, 
                    'ColorBlendJitter': 0, 
                    'HueVariance': App.Constants.VarianceMethod.None, 
                    'HueJitter': 0, 
                    'SaturationVariance': App.Constants.VarianceMethod.None, 
                    'SaturationJitter': 0, 
                    'LightnessVariance': App.Constants.VarianceMethod.None, 
                    'LightnessJitter': 0, 
                    'PositionJitter': 0, 
                    'UseScaledPositionJitter': App.Constants.Boolean.false, 
                    'ImpressionsPerStep': 1
                    }, 
                'Shape': App.Constants.BrushShape.Rectangular,
                'CustomBrush': None, 
                'Size': dropper*2+1, 
                'Hardness': 100, 
                'Density': 100, 
                'Rotation': 0, 
                'Thickness': 100, 
                'Step': 25
                }, 
            'Brush': {
                'Opacity': 100, 
                'ContinuousPaint': App.Constants.Boolean.false, 
                'WetLookPaint': App.Constants.Boolean.false, 
                'BlendMode': App.Constants.BlendMode.Normal
                }, 
            'PrimaryMaterial': App.Constants.MaterialRef.Foreground, 
            'ForegroundMaterial': {
                'Color': (0,0,0), 
                'Pattern': None, 
                'Gradient': None, 
                'Texture': None, 
                'Identity': u'Material'
                }, 
            'BackgroundMaterial': {
                'Color': (255,255,255), 
                'Pattern': None, 
                'Gradient': None, 
                'Texture': None, 
                'Identity': u'Material'
                }, 
            'Stroke': [
                (App.Constants.PathEntryInterpretation.Absolute,(x,y),0)
            ], 
            'GeneralSettings': {
                'ExecutionMode': App.Constants.ExecutionMode.Default, 
                'RandomSeed': 3236927, 
                'AutoActionMode': App.Constants.AutoActionMode.Match
                }
            })
    return Material['Color']

#determine average and sigma of an array
def averagesigma(array):
    x=0
    x2=0
    avsig=[0,0]
    n=len(array)
    for i in range (0,n):
       x=x+array[i]
       x2=x2+array[i]*array[i]
    avsig[0]=x/n
    avsig[1]=sqrt((x2-x*x/n)/(n-1) )
    return avsig

def setupcard(Environment):
    if cardkeuze=='ifrao':
        setupcardifrao(Environment)
    if cardkeuze=='ifraom':
        setupcardifraomacro(Environment)
    if cardkeuze=='pietje':
        setupcardpietje(Environment)
    if cardkeuze=='pietjem':
        setupcardpietjemacro(Environment)
    if cardkeuze=='macbeth':
        setupcardmacbeth(Environment) 
    return

def setupcardifraomacro(Environment):
    setupcardpietjemacro(Environment)
    return

def setupcardpietjemacro(Environment):
    global gemetenkleur

    imagecard=Image.open(cardloc)
    heightcard=imagecard.size[1]
    widthcard=imagecard.size[0]
#initialization of patch dimensions
    stepx=[0,0]
    stepy=[0,0]
    dropper=[0,0]
    patchsidex=widthcard/4.
    patchsidey=heightcard/4.
    stepx[0]=patchsidex/5.
    stepx[1]=patchsidex
    stepy[0]=patchsidey
    stepy[1]=patchsidey*3.
    for i in range(0,rowcard):
       dropper[i]=math.floor((stepx[i]/3.-0.5)/2)
       if dropper[i]>5:
          dropper[i]=5
       if dropper[i]<2:
          print >> sys.stderr,'***WARNING: patches in row ',i+1,' are small, should at least (15*15), but is (',math.floor(stepx[i]),',',math.floor(stepy[i]),')'
          dropper[i]=2
#first row of macro card          
    row=0
    column=5.
    patchy=stepy[row]/2
    allblackpatches=[0,0,0,0,0,0,0,0,0,0]
    allwhitepatches=[0,0,0,0,0,0,0,0,0,0]
    for column2 in range(0,10):
       patchx=((column2*2)+0.5)*stepx[row]
       patchc=measure (Environment,patchx,patchy,dropper[row])
       if column2==column-1:
           gemetenkleur[0]=patchc
       allwhitepatches[column2]=patchc[0] * 0.299 + patchc[1] *0.587 + patchc[2] * 0.114        
    for column2 in range(0,10):
       patchx=((column2*2+1)+0.5)*stepx[row]
       patchc=measure (Environment,patchx,patchy,dropper[row])
       if column2==column-1:
           gemetenkleur[1]=patchc
       allblackpatches[column2]=patchc[0] * 0.299 + patchc[1] *0.587 + patchc[2] * 0.114 
    print "All black patches: ",allblackpatches       
    print "All white patches: ",allwhitepatches  
    avgsigblack=averagesigma(allblackpatches) 
    avgsigwhite=averagesigma(allwhitepatches)     
    print '[Average,sigma] of black and white patches: ', avgsigblack," ",avgsigwhite
    if avgsigblack[0]/(0.001+avgsigblack[1])<10:
       print >> sys.stderr,'***WARNING: The variation of black patches is more than 10% of its average value (', round(avgsigblack[1]/(avgsigblack[0]+0.001)*100),' [%])'     
    if avgsigwhite[0]/(0.001+avgsigwhite[1])<10:
       print >> sys.stderr,'***WARNING: The variation of white patches is more than 10% of its average value (', round(avgsigwhite[1]/(0.001+avgsigwhite[0])*100),' [%])'    
#second row of macro card          
    row=1
    for column in range(1,5):
       patchy=stepy[row-1]+stepy[row]/2
       patchx=((column-1)+0.5)*stepx[row]
       gemetenkleur[column+1]=measure (Environment,patchx,patchy,dropper[row])
    return


def setupcardifrao(Environment):
    global gemetenkleur

    imagecard=Image.open(cardloc)
    heightcard=imagecard.size[1]
    widthcard=imagecard.size[0]
#initialization of patch dimensions
    stepx=[0,0,0]
    stepy=[0,0,0]
    dropper=[0,0,0]
    patchsidex=widthcard/5.
    patchsidey=heightcard/2.
    stepx[0]=patchsidex/2.
    stepx[1]=patchsidex
    stepx[2]=patchsidex
    stepy[0]=patchsidey/2.
    stepy[1]=patchsidey/2.
    stepy[2]=patchsidey
    for i in range(0,rowcard):
       dropper[i]=math.floor((stepy[i]/3.-0.5)/2)
       if dropper[i]>5:
          dropper[i]=5
       if dropper[i]<2:
          print >> sys.stderr,'***WARNING: patches in row ',i+1,' are small, should at least (15*15), but is (',math.floor(stepx[i]),',',math.floor(stepy[i]),')'
          dropper[i]=2
#first row of ifrao card          
    row=0
    column=5.
    patchy=stepy[row]/2
    allblackpatches=[0,0,0,0,0]
    allwhitepatches=[0,0,0,0,0]
    for column2 in range(0,5):
       patchx=((column2*2)+0.5)*stepx[row]
       patchc=measure (Environment,patchx,patchy,dropper[row])
       allwhitepatches[column2]=patchc[0] * 0.299 + patchc[1] *0.587 + patchc[2] * 0.114 
    for column2 in range(0,5):
       patchx=((column2*2+1)+0.5)*stepx[row]
       patchc=measure (Environment,patchx,patchy,dropper[row])
       if column2==column-1:
           gemetenkleur[0]=patchc
       allblackpatches[column2]=patchc[0] * 0.299 + patchc[1] *0.587 + patchc[2] * 0.114 
    print "All black patches: ",allblackpatches       
    print "All white patches: ",allwhitepatches  
    avgsigblack=averagesigma(allblackpatches) 
    avgsigwhite=averagesigma(allwhitepatches)     
    print '[Average,sigma] of black and white patches: ', avgsigblack," ",avgsigwhite
    if avgsigblack[0]/(0.001+avgsigblack[1])<10:
       print >> sys.stderr,'***WARNING: The variation of black patches is more than 10% of its average value (', round(avgsigblack[1]/(avgsigblack[0]+0.001)*100),' [%])'     
    if avgsigwhite[0]/(0.001+avgsigwhite[1])<10:
       print >> sys.stderr,'***WARNING: The variation of white patches is more than 10% of its average value (', round(avgsigwhite[1]/(0.001+avgsigwhite[0])*100),' [%])'    
#second row of ifrao card          
    row=1
    for column in range(3,6):
       patchy=stepy[row-1]+stepy[row]/2
       patchx=((column-1)+0.5)*stepx[row]
       gemetenkleur[column-2]=measure (Environment,patchx,patchy,dropper[row])
#third row of ifrao card          
    row=2
    for column in range(2,6):
       patchy=stepy[row-1]+stepy[row-2]+stepy[row]/2
       patchx=((column-1)+0.5)*stepx[row]
       gemetenkleur[column+2]=measure (Environment,patchx,patchy,dropper[row])
    return

def setupcardpietje(Environment):
    global gemetenkleur
    imagecard=Image.open(cardloc)
    heightcard=imagecard.size[1]
    widthcard=imagecard.size[0]
#initialization of patch dimensions
    stepx=widthcard/5.
    stepy=heightcard/4.
    dropper=math.floor((stepy/3.-0.5)/2)
    if dropper>5:
          dropper=5
    if dropper<2:
          print >> sys.stderr,'***WARNING: patches in all rows are small, should at least (15*15), but is (',math.floor(stepx),',',math.floor(stepy),')'
          dropper=2
#first row of pietje card          
    row=0
    column=4
    patchy=stepy/2
    allblackpatches=[0,0]
    patchx=stepx/4
    patchc=measure (Environment,patchx,patchy,dropper)
    allblackpatches[0]=patchc[0]*0.299 + patchc[1]*0.587 + patchc[2]*0.114 
    for column2 in range(1,5):
       patchx=column2*stepx
       patchc=measure (Environment,patchx,patchy,dropper)
       gemetenkleur[column2-1]=patchc
       if column2==column:
           allblackpatches[1]=patchc[0]*0.299 + patchc[1]*0.587 + patchc[2]*0.114 
    print "All black patches: ",allblackpatches       
    avgsigblack=averagesigma(allblackpatches) 
    print '[Average,sigma] of black patches: ', avgsigblack
    if avgsigblack[0]/(0.001+avgsigblack[1])<10:
       print >> sys.stderr,'***WARNING: The variation of black patches is more than 10% of its average value (', round(avgsigblack[1]/(avgsigblack[0]+0.001)*100),' [%])'     
#second row of pietje card          
    row=1
    for column in range(2,6):
       patchy=stepy*1.5
       patchx=((column-1)+0.5)*stepx
       gemetenkleur[column-2+row*4]=measure (Environment,patchx,patchy,dropper)
#third row of pietje card          
    row=2
    for column in range(1,5):
       patchy=stepy*2.5
       patchx=((column-1)+0.5)*stepx
       gemetenkleur[column-1+row*4]=measure (Environment,patchx,patchy,dropper)
#forth row of pietje card          
    row=3
    for column in range(1,5):
       patchy=stepy*3.5
       patchx=((column-1)+0.5)*stepx
       gemetenkleur[column-1+row*4]=measure (Environment,patchx,patchy,dropper)
    return

def setupcardmacbeth(Environment):
    global gemetenkleur
    imagecard=Image.open(cardloc)
    heightcard=imagecard.size[1]
    widthcard=imagecard.size[0]
#initialization of patch dimensions
    stepx=widthcard/6.
    stepy=heightcard/4.
    dropper=math.floor((stepy/3.-0.5)/2)
    if dropper>5:
          dropper=5
    if dropper<2:
          print >> sys.stderr,'***WARNING: patches in all rows are small, should at least (15*15), but is (',math.floor(stepx),',',math.floor(stepy),')'
          dropper=2
#rows of macbeth card          
    for row in range(0,4):
      for column in range(1,7):
       patchy=stepy*(row+0.5)
       patchx=((column-1)+0.5)*stepx
       gemetenkleur[column-1+row*6]=measure (Environment,patchx,patchy,dropper)
    return



#calculate a gamma function
def detergamma(x):
  return 255*math.pow(float(x)/255,gamma)

#display picture
def displaypic(pix,titletext):
     w2=ImageWin.ImageWindow(pix,title=titletext)
     w2.mainloop() # this will block until the window is closed
     return

def optimummaking():

 global gamma

#read picture
 imbegin = Image.open(imagelocation)
 
# just a sample color matrix (I kept the off-set zero (the last
# 'column' with zeros)
 colormat= (colormatrixopt[0],colormatrixopt[3],colormatrixopt[6],0,	
        colormatrixopt[1],colormatrixopt[4],colormatrixopt[7],0,	
        colormatrixopt[2],colormatrixopt[5],colormatrixopt[8],0)
 	   

#bring picture in linear space, assume it was near srgb
#first split it in the three bands, to be able to do
#different gamma on each band
 splitted= imbegin.split()
 gamma=1/gbopt[0]
 Rrr=Image.eval(splitted[0], detergamma)
 gamma=1/gbopt[1]
 Ggg=Image.eval(splitted[1], detergamma)
 gamma=1/gbopt[2]
 Bbb=Image.eval(splitted[2], detergamma)

#make it one RGB picture
 combined=Image.merge("RGB",(Rrr,Ggg,Bbb))

#do a color matrix transform
 converted = combined.convert("RGB", colormat)
#bring back into srgb space
 gamma=1/ge[0]
 imend=Image.eval(converted, detergamma)

 imend.save(optimumloc)
 return


def optfunction(xx):
    gemeten=gemetenkleur[:]
    gammakleuren=gammakleur(gemetenkleur,xx[9:12])
    transposekleur= matrixkleur(gammakleuren,xx[0:9],0)
    endkleur=gammakleur(transposekleur,ge)
    y=verschil(endkleur,doelkleur)
    return y

def test(mat,n):
    errorteller=0
    for testprim in range(0,numberprimcolors):
      errorteller=errorteller+testcolor(mat[testprim],n,primkleur[testprim])
    return errorteller

def testcolor(color,n,m):
    if color<=round(threshold+0.5):
     print >> sys.stderr,'***WARNING: ',m, ' channel of ',n,' patch is underexposed: ',color
     return 1
    if color>=255-round(threshold+0.5):
     print >> sys.stderr,'***WARNING: ',m, ' channel of ',n,' patch is overexposed: ',color
     return 1
    return 0
    
def testinggemetenkleur():
    global ok
    okteller=0
    for patchcolor in range(0,numbercolors):
      teller=test(gemetenkleur[patchcolor],patch[patchcolor])
      if teller>1:
        ok[patchcolor]=0
        print >> sys.stderr,'***ERROR: ',patch[patchcolor],' patch removed from optimization: ',teller
      else:
        ok[patchcolor]=1
        okteller=okteller+1
    if okteller<2:
        print >> sys.stderr,'***ERROR: at least two color patches must be available to optimize, now only: ',okteller
        stopscript()
    if okteller<0.75*numbercolors:
        print >> sys.stderr,'***WARNING: Only ',okteller,' color patches take part in optimization'   
        
    #determine the back&white values of the color patches
    for i in range(0,numbercolors):
           bwvalue[i]=round(gemetenkleur[i][0]*0.299 + gemetenkleur[i][1]*0.587 + gemetenkleur[i][2]*0.114 +0.5)
    print 'Black&white values of color patches: ',bwvalue
    
    #make sure that the darker b&W patch colors are indeed darker then the lighter colors.
    for i in range(0,bws-1):
       if bwvalue[BWrange[i]]+threshold>bwvalue[BWrange[i+1]]:
          ok[i]=0
          print >> sys.stderr,'***ERROR: ',patch[BWrange[i]],' patch removed from optimization, should be darker then ',patch[BWrange[i+1]]
    print 'Accepted colorpatches: ',ok
    
    return

def findcolors(Environment):
    Material = App.Do( Environment, 'GetMaterial', {'IsPrimary': App.Constants.Boolean.true,
                'GeneralSettings': {
                'ExecutionMode': App.Constants.ExecutionMode.Silent,
                'AutoActionMode': App.Constants.AutoActionMode.Match
                }
    })
    oudekleur=Material['Color']
    for patchcolor in range(0,numbercolors):
      print 'Pick ',patch[patchcolor],' color patch, and press <OK>'
      Material = App.Do( Environment, 'GetMaterial', {'IsPrimary': App.Constants.Boolean.true})
      gemetenkleur[patchcolor]=Material['Color']
      if Material['Color']==oudekleur:
          stopscript()
      oudekleur=Material['Color']
    print gemetenkleur
    return

def gammakleur(kleuren,gamma):
    kleurenopbouw=[]
    for i in range(0,numbercolors):
      kleurenopbouw.append([0,0,0])
    for x in range(0,numbercolors):
        kleur=[0,0,0]
        for y in range(0,numberprimcolors):
            if gamma[y]<=0:
               gamma[y]=0.0001
            kleur[y]=255*math.pow(float(kleuren[x][y])/255,float(1/(gamma[y])))
        kleurenopbouw[x]=kleur
    return kleurenopbouw

def verschil(kleurena,kleurenb):
    verschil=0
    teller=0
    for x in range(0,numbercolors):
        if ok[x]==1:
           teller=teller+1
        for y in range(0,numberprimcolors):
            verschil=verschil+math.pow(float(kleurena[x][y]-kleurenb[x][y]),2)*ok[x]
    return math.sqrt(verschil/teller)

def integerkleur(kleuren):
    kleurenopbouw=[]
    for i in range(0,numbercolors):
      kleurenopbouw.append([0,0,0])
    for x in range(0,numbercolors):
        for y in range(0,numberprimcolors):
            kleurenopbouw[x][y]=math.floor(kleuren[x][y]+0.5)
    return kleurenopbouw


def fixgamma(gamma):
    gammaint=[0,0,0]
    for y in range(0,numberprimcolors):
            gammaint[y]=math.floor((gamma[y]+0.5/100)*100)/100
    return gammaint


def matrixkleur(kleuren,matrix,gamutprinting):
    kleurenopbouw=[]
    for i in range(0,numbercolors):
      kleurenopbouw.append([0,0,0])
    for x in range(0,numbercolors):
        kleur=[0,0,0]
        teller=0
        valuemin=0
        valuemax=255
        for y in range(0,numberprimcolors):
             kleur[y]=kleuren[x][0]*matrix[3*0+y]+kleuren[x][1]*matrix[3*1+y]+kleuren[x][2]*matrix[3*2+y]
             if kleur[y]<0:
                teller=teller+1
                if kleur[y]<valuemin:
                   valuemin=kleur[y]
                kleur[y]=0
             if kleur[y]>255:
                if kleur[y]>valuemax:
                   valuemax=kleur[y]
                teller=teller+1
                kleur[y]=255
        kleurenopbouw[x]=kleur
        if gamutprinting and teller>0:
            print >> sys.stderr,'***WARNING: ',patch[x],' patch was out of gamut: (',math.floor(valuemin),' ',math.floor(valuemax),')'
    return kleurenopbouw

def initPSP(Environment):

  # ShowScriptToolbar
  App.Do( Environment, 'ShowScriptToolbar', {
            'ShowScriptBar': App.Constants.ShowCommands.Show,
            'GeneralSettings': {
                'ExecutionMode': App.Constants.ExecutionMode.Silent,
                'AutoActionMode': App.Constants.AutoActionMode.Match
                }
            })

  #select eyedropper tool
  App.Do( Environment, 'SelectTool', { 'Tool': 'Eyedropper' } )

  #determine PSP version
  Version = App.Do(Environment, 'GetVersionInfo')
  minorversion=Version['MajorVersion']
  versie = r'Software\Jasc\Paint Shop Pro %d\General' % (minorversion)
  # open the psp general key
  key = _winreg.OpenKey( _winreg.HKEY_CURRENT_USER, versie )
  # get the currently selected scriptmode in the script droplist.
  val = _winreg.QueryValueEx( key, 'SelectScriptMode' )
  # this is the selected scriptmode
  Mode = val[0]
  #if insilent mode, put it in interactive script mode
  if Mode==2:
  # SetExecutionMode
   App.Do( Environment, 'SetExecutionMode', {
             'GeneralSettings': {
                 'ExecutionMode': App.Constants.ExecutionMode.Default,
                 'AutoActionMode': App.Constants.AutoActionMode.Match
                 }
             })

  #Show Script OUtput Palette
  App.Do( Environment, 'ShowScriptOutput', {
            'ShowScriptOutput': App.Constants.ShowCommands.Show,
            'GeneralSettings': {
                'ExecutionMode': App.Constants.ExecutionMode.Silent,
                'AutoActionMode': App.Constants.AutoActionMode.Match
                }
            })

  #chnage picture to 16 Million colors (if needed)
  try:
    if App.Do( Environment, 'CountImageColors', {
            'GeneralSettings': {
                'ExecutionMode': App.Constants.ExecutionMode.Silent, 
                'AutoActionMode': App.Constants.AutoActionMode.Match
                }
            }) <= 255:

        App.Do( Environment, 'IncreaseColorsTo16Million', {
            'GeneralSettings': {
                'ExecutionMode': App.Constants.ExecutionMode.Silent, 
                'AutoActionMode': App.Constants.AutoActionMode.Match
                }
            }) 
  except:
         pass
  return
  

def UpdateEXIF(Environment,colorspace,verschil):
  Info = App.Do( Environment, 'ReturnImageInfo' )
  comment = Info['ExifTitle']
  comment=comment+'File adjusted by optimization software of V. Reijs, (c) 2005 towards '+colorspace.upper()+' colorspace using '+cardkeuze.upper()+' ('+yearkeuze+') color scale. The difference with '+cardkeuze.upper()+' color scale is: '+str(verschil)

  App.Do( Environment, 'ImageInfo', {
            'ExifTitle': comment,
             'GeneralSettings': {
                'ExecutionMode': App.Constants.ExecutionMode.Silent,
                'AutoActionMode': App.Constants.AutoActionMode.Match
                }
            })
  print comment
  return

def stopscript():
            print >> sys.stderr,'***WARNING: Optimization stopped'
            print '*************'
            sys.exit()

def initcard():
    global numbercolors
    global patch
    global rowcard
    global BWrange    
    global bws
    global ok
    global bwvalue
    global gemetenkleur
    
    if cardkeuze=='ifrao':
       numbercolors=numbercolorsifrao
       patch=patchifrao
       rowcard=rowcardifrao
       BWrange=BWrangeifrao
       
    if cardkeuze=='ifraom':
       numbercolors=numbercolorsifraomacro
       patch=patchifraomacro
       rowcard=rowcardifraomacro
       BWrange=BWrangeifraomacro
       
    if cardkeuze=='pietje':
       numbercolors=numbercolorspietje
       patch=patchpietje
       rowcard=rowcardpietje
       BWrange=BWrangepietje

    if cardkeuze=='pietjem':
       numbercolors=numbercolorspietjemacro
       patch=patchpietjemacro
       rowcard=rowcardpietjemacro
       BWrange=BWrangepietjemacro

    if cardkeuze=='macbeth':
       numbercolors=numbercolorsmacbeth
       patch=patchmacbeth
       rowcard=rowcardmacbeth
       BWrange=BWrangemacbeth
       
    bws=len(BWrange)
    ok=[]
    bwvalue=[]
    gemetenkleur=[]
    for i in range (0,numbercolors):
       ok.append(0)
       bwvalue.append(0)
       gemetenkleur.append([0,0,0])
    return
    
        
def determinecard(Environment):
    global cardkeuze
    global yearkeuze
    
    #determine the type of color scale
    nogniet=0
    while nogniet==0:
         keuze =App.Do( Environment, 'GetString', {'DefaultText': 'ifrao','DialogTitle': 'Question?','Prompt': 'What scale type:\rifrao, ifraom, pietje, pietjem or macbeth?','MaxLength': 7})
         cardkeuze=keuze[ 'EnteredText' ].lower()
         if cardkeuze=='ifrao':
            nogniet=1
         if cardkeuze=='ifraom':
            nogniet=1
         if cardkeuze=='pietje':
            nogniet=1
         if cardkeuze=='pietjem':
            nogniet=1
         if cardkeuze=='macbeth':
            nogniet=1
         if keuze['OKButton']==0:
            stopscript()
            
    #determine the version year of the IFRAO standard scale
    nogniet=0
    if cardkeuze=='ifrao' or cardkeuze=='ifraom':
      while nogniet==0:
         keuze =App.Do( Environment, 'GetString', {'DefaultText': '2001','DialogTitle': 'Question?','Prompt': 'Year of used ifrao standard scale:\r1994 or 2001?','MaxLength': 4})
         yearkeuze=keuze[ 'EnteredText' ]
         if yearkeuze=='1994':
            nogniet=1
         if yearkeuze=='2001':
            nogniet=1
         if keuze['OKButton']==0:
            stopscript()
    
    #detemine the version year of PIETJE color scale
    nogniet=0
    if cardkeuze=='pietje' or cardkeuze=='pietjem':
         print >> sys.stderr,'***ERROR: PIETJE color scale does not have yet proper target colors, so results are wrong'
         stopscript()
         keuze =App.Do( Environment, 'GetString', {'DefaultText': '2005','DialogTitle': 'Question?','Prompt': 'Year of used pietje standard scale:\r2005?','MaxLength': 4})
         yearkeuze=keuze[ 'EnteredText' ]
         if yearkeuze=='2005':
            nogniet=1
         if keuze['OKButton']==0:
            stopscript()
            
    #inititilize the scale parameters
    initcard()       
    print cardkeuze.upper(),' version year: ',yearkeuze
    return


def determinetarget(space):
    global doelkleur
    if cardkeuze=='ifrao':
       if yearkeuze=='1994':
          if space=='srgb':
             doelkleur=ifrao1994srgb
          else:
             doelkleur=ifrao1994Adobe   
       else:
          if space=='srgb':
             doelkleur=ifrao2001srgb
          else:
             doelkleur=ifrao2001Adobe   
    if cardkeuze=='ifraom':
       if yearkeuze=='1994':
          if space=='srgb':
             doelkleur=ifraomacro1994srgb
          else:
             doelkleur=ifraomacro1994Adobe   
       else:
          if space=='srgb':
             doelkleur=ifraomacro2001srgb
          else:
             doelkleur=ifraomacro2001Adobe   
    if cardkeuze=='pietje':
          if space=='srgb':
             doelkleur=pietje2005srgb
          else:
             doelkleur=pietje2005Adobe   
    if cardkeuze=='pietjem':
          if space=='srgb':
             doelkleur=pietjemacro2005srgb
          else:
             doelkleur=pietjemacro2005Adobe   
    if cardkeuze=='macbeth':
          if space=='srgb':
             doelkleur=macbethsrgb
          else:
             doelkleur=macbethAdobe   
    return  
    
def opencloseopen(Environment,filename):
  fileresult=0
  if os.path.exists(filename):
    fileresult=1
    App.Do( Environment, 'FileOpen', {
            'FileList': [filename ],
            'GeneralSettings': {
                'ExecutionMode': App.Constants.ExecutionMode.Silent, 
                'AutoActionMode': App.Constants.AutoActionMode.Match
                }
            })
    if fileresult==1:
      App.Do( Environment, 'SelectDocument', {
            'SelectedImage': 0, 
            'Strict': App.Constants.Boolean.false, 
            })
         
#      if filename.find("scale")<>-1:
#       try: 
##        App.Do( Environment, 'UndoLastCmd', {            
#        'GeneralSettings': {
#                'ExecutionMode': App.Constants.ExecutionMode.Silent, 
#                'AutoActionMode': App.Constants.AutoActionMode.Match
#                }
#         })
#       except:
#        pp=0
      App.Do( Environment, 'FileClose', {
            'GeneralSettings': {
                'ExecutionMode': App.Constants.ExecutionMode.Silent, 
                'AutoActionMode': App.Constants.AutoActionMode.Match
                }
            })
      App.Do( Environment, 'FileOpen', {
            'FileList': [filename],
            'GeneralSettings': {
                'ExecutionMode': App.Constants.ExecutionMode.Silent, 
                'AutoActionMode': App.Constants.AutoActionMode.Match
                }
            })
      App.Do( Environment, 'SelectDocument', {'SelectedImage': 0,   
            'Strict': App.Constants.Boolean.false})
  return fileresult              

def Do(Environment):
  global imagelocation
  global optimumloc
  global cardloc

  global colormatrixopt
  global gbopt

  print ''
  print '*************'
  print >> sys.stderr,'Victor Reijs, (c) 2005, version: ',version
  print >> sys.stderr,'http://www.iol.ie/~geniet/eng/ifraocoloropt.htm#Method'
  
  #determine if file is active, if not active stop optimization
  if App.ActiveDocument<>None:
    imagelocation=App.ActiveDocument.Name
    print 'Original file is at: ',imagelocation
    
    #determine file names for optimum and card files
    optimumloc=imagelocation.split(".")[0]+"-optimum."+imagelocation.split(".")[1]
    cardloc=imagelocation.split(".")[0]+"-scale."+imagelocation.split(".")[1]
    pickedcardloc=imagelocation.split(".")[0]+"-pickedscale."+imagelocation.split(".")[1]
    
    #determine if file type is allowed in Image module 
    try:
      imbegin = Image.open(imagelocation)
    except:
      print >> sys.stderr,'***ERROR: File type ',imagelocation.split(".")[1],' not supported'
      stopscript()
         
    #determine if RGB bands are within the image file 
    if imbegin.mode<>"RGB":
      print >> sys.stderr,'***ERROR: No RGB bands available in ',imagelocation.split(".")[1],' file'
      stopscript()  
    
    #initialize PSP 
    initPSP(Environment)   
    
    #determine which scale needs to be investigated 
    determinecard(Environment)
    
    #determine if one wants to auto pick or hand pick the reference colors
    result = App.Do(Environment, 'MsgBox', {'Buttons': App.Constants.MsgButtons.YesNo,'Icon': App.Constants.MsgIcons.Info,'Text': 'Do you want to hand pick the color pacthes yourself: press Yes\ror auto pick them using a seperate "-scale" file: press No',})

    #keep on asking for colors until they have been determined in some way (hand/auto)
    resultfile=0          
    while resultfile==0:
      resultfile=1
      
      #hand pick colors
      if result==1:
         findcolors(Environment)
                 
      #autopick colors
      else:
        resultfile=opencloseopen(Environment,cardloc) 
        
        #no file with scale available
        if resultfile==0:
            resultno = App.Do(Environment, 'MsgBox', {'Buttons': App.Constants.MsgButtons.YesNo,'Icon': App.Constants.MsgIcons.Info,'Text': '***ERROR: No file explicitly available with "-scale" in the name.\rDo you want to hand pick: press Yes\ror end the optimization: press No'})
            result=1
            if resultno==0:
               stopscript() 
                
        #autopick the colors in the scale    
        if resultfile==1:
          setupcard(Environment)
#          print pickedcardloc
#          print cardloc
#          App.Do( Environment, 'FileSave', {
#            'FileList': [ pickedcardloc ],
#            'GeneralSettings': {
#                'ExecutionMode': App.Constants.ExecutionMode.Silent, 
#                'AutoActionMode': App.Constants.AutoActionMode.Match
#                }
#            })
          
    #test if all the picked colors are oke
    testinggemetenkleur()
    
    #determine what the target color space should be
    nogniet=0
    while nogniet==0:
         keuze =App.Do( Environment, 'GetString', {'DefaultText': 'srgb','DialogTitle': 'Question?','Prompt': 'What target colorspace is needed:\rsrgb or adobergb?','MaxLength': 9})
         spacekeuze=keuze[ 'EnteredText' ].lower()
         if spacekeuze=='srgb':
            nogniet=1
         if spacekeuze=='adobergb':
            nogniet=1
         if keuze['OKButton']==0:
            stopscript()
    print 'Target colorspace: ',spacekeuze
            
    #determine the target colors needed for the optimization
    determinetarget(spacekeuze)
    
    #determine optimum array (door fmin_bfgs of scipy)
    totaal=colormatrix+gb
    xopt = fmin_bfgs(optfunction, totaal, args=(), maxiter=10000)
    
    #put the optimized array in colormatrix and gamma begin array
    colormatrixopt=xopt[0:9]
    gbopt=xopt[9:12]
    
    #calculate and present all the intermediate steps of the process to gain the optimum picture
    print 'Measured colors: ', integerkleur(gemetenkleur)
    verschilbegin=verschil(gemetenkleur,doelkleur)/threshold
    print 'Start difference: ',verschilbegin
    print 'Start gamma: ',fixgamma(gbopt)
    gammakleuren=gammakleur(gemetenkleur,gbopt)
    print 'Lineair colors: ', integerkleur(gammakleuren)
    print 'Color matrix: ',colormatrixopt
    transposekleur= matrixkleur(gammakleuren,colormatrixopt,1)
    print 'Transpose colors: ', integerkleur(transposekleur)
    print 'End gamma: ',fixgamma(ge)
    endkleur=gammakleur(transposekleur,ge)
    print 'Final colors: ', integerkleur(endkleur)
    print 'Target colors: ', integerkleur(doelkleur)
    verschilend=verschil(endkleur,doelkleur)/threshold
    print 'End difference: ',verschilend
    if verschilbegin==0:
       print 'No difference between measured colors and target colors'  
    else:
       print 'Difference reduced to ',math.floor(verschilend/(verschilbegin)*100),'% of start difference'
       
    # make the optimum picture
    optimummaking()
    
    # add EXIF info in optimum picture
    opencloseopen(Environment,optimumloc) 
    UpdateEXIF(Environment,spacekeuze,round(verschilend+0.5))
    
    #save optimum picture with EXIF info
    App.Do( Environment, 'FileSave', {
            'FileList': [ optimumloc ],
            'GeneralSettings': {
                'ExecutionMode': App.Constants.ExecutionMode.Silent, 
                'AutoActionMode': App.Constants.AutoActionMode.Match
                }
            })
    print 'Optimized file is at: ',optimumloc

  else:
    print >> sys.stderr,'***ERROR: No picture active'
  print '*************'

