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



version=0.1
numbercolors=8
numberprimcolors=3
threshold=3
#should be 2.8
black=0
darkgrey=1
grey=2
white=3
blue=4
green=5
yellow=6
red=7
patch=['black','darkgrey','grey','white','blue','green','yellow','red']
primkleur=['red','green','blue']
ok=[1,1,1,1,1,1,1,1]
bmifrao1bmp=[(41, 37, 33), (63, 56, 53), (107, 97, 92), (228, 226, 222), (81, 64, 107), (107, 131, 82), (236, 207, 71), (158, 58, 42)]
gemetenkleur=[(41, 37, 33), (63, 56, 53), (107, 97, 92), (228, 226, 222), (81, 64, 107), (107, 131, 82), (236, 207, 71), (158, 58, 42)]
gammakleuren=[[47,46,47],[62,65,61],[116,114,114],[238,233,232],[65,62,116],[0,144,75],[245,211,0],[207,65,60]]
endkleur=[[47,46,47],[62,65,61],[116,114,114],[238,233,232],[65,62,116],[0,144,75],[245,211,0],[207,65,60]]
doelkleur=[[47,46,47],[62,65,61],[116,114,114],[238,233,232],[65,62,116],[0,144,75],[245,211,0],[207,65,60]]
ifrao1994sRGB=[[47,46,47],[62,65,61],[116,114,114],[238,233,232],[65,62,116],[0,144,75],[245,211,0],[207,65,60]]
ifrao2001sRGB=[[35,35,38],[63,65,65],[124,122,121],[235,234,240],[81,79,129],[0,150,82],[237,216,20],[194,67,53]]
ifrao1994Adobe=[[50,50,51],[65,67,64],[115,114,113],[236,233,231],[66,64,114],[77,142,80],[235,210,43],[179,67,62]]
ifrao2001Adobe=[[40,40,42],[66,67,67],[123,121,120],[234,233,240],[82,80,127],[84,148,87],[230,214,56],[169,68,56]]
gbi=[0.45455,0.45455,0.45455]
gbbmifrao1bmp=[0.44,0.50,0.51]
gb=[0.45455,0.45455,0.45455]
ge=[2.2,2.2,2.2]
colormatrixi=[1.,0.,0.,0.,1.,0.,0.,0.,1.]
colormatrixbmifrao1bmp=[2,-0.01,0.06,-1.06,1.11,-0.22,0.08,-0.09,1.25]
colormatrix=[1.,0.,0.,0.,1.,0.,0.,0.,1.]


#http://www.vallis.org/software/Simplex.py
#http://pylab.sourceforge.net/
#http://pylab.sourceforge.net/packages/optimize.py
#http://www.ifi.uio.no/~inf3330/scripting/doc/python/SciPy/tutorial/node11.html
#http://www.scipy.org/


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<=threshold:
     print >> sys.stderr,'***WARNING: ',m, ' channel of ',n,' patch is underexposed: ',color
     return 1
    if color>=255-threshold:
     print >> sys.stderr,'***WARNING: ',m, ' channel of ',n,' patch is overexposed: ',color
     return 1
    return 0

def findcolor(Environment,patchcolor):
    print 'Pick ',patch[patchcolor],' color patch, and press <OK>'
#remove below hash if one wants to choice the color
    Material = App.Do( Environment, 'GetMaterial', {'IsPrimary': App.Constants.Boolean.true})
    gemetenkleur[patchcolor]=Material['Color']
    teller=test(gemetenkleur[patchcolor],patch[patchcolor])
    if teller>1:
      ok[patchcolor]=0
      print >> sys.stderr,'***ERROR: ',patch[patchcolor],' patch removed from optimization: ',teller

def gammakleur(kleuren,gamma):
    kleurenopbouw=[[47,46,47],[62,65,61],[116,114,114],[238,233,232],[65,62,116],[0,144,75],[245,211,0],[207,65,60]]
    for x in range(0,numbercolors):
        kleur=[0,0,0]
        for y in range(0,numberprimcolors):
            kleur[y]=255*math.pow(float(kleuren[x][y])/255,float(1/(0.00000001+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=[[47,46,47],[62,65,61],[116,114,114],[238,233,232],[65,62,116],[0,144,75],[245,211,0],[207,65,60]]
    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 checkminmaxmatrix(matrix):
    for x in range(0,numberprimcolors):
        for y in range(0,numberprimcolors):
             if matrix[3*x+y]>2:
                print >> sys.stderr,'***ERROR: matrix cell (',primkleur[x],',',primkleur[y],') is higher then 2: ',math.floor(matrix[3*x+y]*10)/10
                matrix[3*x+y]=2
             if matrix[3*x+y]<-2:
                print >> sys.stderr,'***ERROR: matrix cell (',primkleur[x],',',primkleur[y],') is lower then -2: ',math.floor(matrix[3*x+y]*10)/10
                matrix[3*x+y]=-2
                

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=[[47,46,47],[62,65,61],[116,114,114],[238,233,232],[65,62,116],[0,144,75],[245,211,0],[207,65,60]]
    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
                }
            })
              
              
  App.Do( Environment, 'SelectTool', { 'Tool': 'Eyedropper' } )
  
  Version = App.Do(Environment, 'GetVersionInfo')
  minorversion=Version['MajorVersion']

#  versie='r'+"'"+'Software\Jasc\Paint Shop Pro '+str(minorversion)+'\General'+"'"
#  versie="'"+'Software\Jasc\Paint Shop Pro '+str(minorversion)+'\General'+"'"
  versie = r'Software\Jasc\Paint Shop Pro %d\General' % (minorversion)
  # open the psp 9 general key
  key = _winreg.OpenKey( _winreg.HKEY_CURRENT_USER, versie )
  # get the currently selected script in the script droplist.
  val = _winreg.QueryValueEx( key, 'SelectScriptMode' )

  # this is the selected script
  Mode = val[0]
  if Mode==2:

  # SetExecutionMode
   App.Do( Environment, 'SetExecutionMode', {
             'GeneralSettings': {
                 'ExecutionMode': App.Constants.ExecutionMode.Default, 
                 'AutoActionMode': App.Constants.AutoActionMode.Match
                 }
             })


  App.Do( Environment, 'ShowScriptOutput', {
            'ShowScriptOutput': App.Constants.ShowCommands.Show, 
            'GeneralSettings': {
                'ExecutionMode': App.Constants.ExecutionMode.Silent, 
                'AutoActionMode': App.Constants.AutoActionMode.Match
                }
            })
  
  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
 
def EndPSP(Environment,colorspace):
  Info = App.Do( Environment, 'ReturnImageInfo' )
  comment = Info['ExifTitle']
  comment=comment+'File adjusted by optimization software of V. Reijs, (c) 2005 towards '+colorspace+' colorspace. '

  App.Do( Environment, 'ImageInfo', {
            'ExifTitle': comment, 
             'GeneralSettings': {
                'ExecutionMode': App.Constants.ExecutionMode.Silent, 
                'AutoActionMode': App.Constants.AutoActionMode.Match
                }
            })
  print comment
 
def stopscript():
            print >> sys.stderr,'***WARNING: Program stopped'
            print '*************'
            sys.exit()


def Do(Environment):
  global gemetenkleur
  global doelkleur
  print ''
  print '*************'
  print >> sys.stderr,'Victor Reijs, (c) 2005, version: ',version
  print >> sys.stderr,'http://www.iol.ie/~geniet/eng/IFRAOcoloropt.htm#Method'
  
  if App.ActiveDocument<>None:
    initPSP(Environment)


    askingcolors=numbercolors
    App.Do( Environment, 'EnableOptimizedScriptUndo', {                       }) 
    nogniet=0
    while nogniet==0:
         year ={ 'EnteredText':'1994'}
         if askingcolors==numbercolors:
            year =App.Do( Environment, 'GetString', {'DefaultText': '2001','DialogTitle': 'Question?','Prompt': 'Year of used IFRAO standard scale: 1994 or 2001?','MaxLength': 4})
         if year[ 'EnteredText' ]=='1994':
            nogniet=1
            keuze=1
         if year[ 'EnteredText' ]=='2001':
            nogniet=1
            keuze=2
         if year['EnteredText']=='stop':
            stopscript()
    print 'IFRAO version year: ',year[ 'EnteredText' ]

    for gekozenkleur in range(0,askingcolors): 
       findcolor(Environment,gekozenkleur)
    if askingcolors<>numbercolors:
       gemetenkleur=gemetenkleur
    print 'Accepted colorpatches: ',ok


    nogniet=0
    while nogniet==0:
         colorspace = {'EnteredText':"sRGB"}
         if askingcolors==numbercolors:
            colorspace =App.Do( Environment, 'GetString', {'DefaultText': 'sRGB','DialogTitle': 'Question?','Prompt': 'What colorspace is needed: sRGB or AdobeRGB?','MaxLength': 9})
         if colorspace[ 'EnteredText' ]=='sRGB':
            nogniet=1
            if keuze==1:
               doelkleur=ifrao1994sRGB
            else:
               doelkleur=ifrao2001sRGB
         if colorspace[ 'EnteredText' ]=='AdobeRGB':
            nogniet=1
            if keuze==1:
               doelkleur=ifrao1994Adobe
            else:
               doelkleur=ifrao2001Adobe
         if colorspace['EnteredText']=='stop':
            stopscript()

    print 'Target colorspace: ',colorspace[ 'EnteredText' ]
    
#bepalen totaal (door fmin_bfgs of scipy)

    totaal=colormatrix+gb
    xopt = fmin_bfgs(optfunction, totaal, args=(), maxiter=10000)
    colormatrixopt=xopt[0:9]
    gbopt=xopt[9:12]

    print 'Measured colors: ', integerkleur(gemetenkleur)
    verschilbegin=verschil(gemetenkleur,doelkleur)
    print 'Start difference: ',verschilbegin
    print 'Start gamma: ',fixgamma(gbopt)
    gammakleuren=gammakleur(gemetenkleur,gbopt)
    print 'Lineair colors: ', integerkleur(gammakleuren)
    print 'Color matrix: ',colormatrixopt
    checkminmaxmatrix(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)
    print 'End difference: ',verschilend
    print 'Difference reduced to ',math.floor(verschilend/verschilbegin*100),'% of start difference'

    # Color Adjust Gamma Correct
    App.Do( Environment, 'ColorAdjustGammaCorrect', {
            'Gamma': {
                'Red': gbopt[0], 
                'Green': gbopt[1], 
                'Blue': gbopt[2]
                }, 
            'GeneralSettings': {
                'ExecutionMode': App.Constants.ExecutionMode.Silent, 
                'AutoActionMode': App.Constants.AutoActionMode.Match
                }
            })

    # Color Adjust Channel Mixer
    App.Do( Environment, 'ColorAdjustChannelMixer', {
            'ChannelMixer': {
                'Monochrome': App.Constants.Boolean.false, 
                'Red': (colormatrixopt[3*0+0]*100,colormatrixopt[3*1+0]*100,colormatrixopt[3*2+0]*100,0), 
                'Green': (colormatrixopt[3*0+1]*100,colormatrixopt[3*1+1]*100,colormatrixopt[3*2+1]*100,0),
                'Blue': (colormatrixopt[3*0+2]*100,colormatrixopt[3*1+2]*100,colormatrixopt[3*2+2]*100,0)
                }, 
            'GeneralSettings': {
                'ExecutionMode': App.Constants.ExecutionMode.Silent, 
                'AutoActionMode': App.Constants.AutoActionMode.Match
                }
            })

    # Color Adjust Gamma Correct
    App.Do( Environment, 'ColorAdjustGammaCorrect', {
            'Gamma': {
                'Red': ge[0], 
                'Green': ge[1], 
                'Blue': ge[2]
                }, 
            'GeneralSettings': {
                'ExecutionMode': App.Constants.ExecutionMode.Silent, 
                'AutoActionMode': App.Constants.AutoActionMode.Match
                }
            })
    EndPSP(Environment,colorspace['EnteredText'])
  else:
    print >> sys.stderr,'***ERROR: No picture active'
  print '*************'

