'xpm Datei'
import os
#==============================================================================
def maxBlau( farben ):
    q   = bton = -1
    ans = ''
    for farbe in farben:
        # farbe='#012345'
        if min( [ s in '#0123456789abcdef' for s in farbe.lower() ] ) == True:
            r = float( eval( '0x%s'%farbe[ 1:3 ] ) )
            g = float( eval( '0x%s'%farbe[ 3:5 ] ) )
            b = float( eval( '0x%s'%farbe[ 5:7 ] ) )
            if r + g == 0:
                if b != 0 and b > bton:
                    bton = farbe
            else:
                s = b/( r + g )
                if s > q:
                    q = s
                    ans = farbe
    if bton > -1:
        ans = bton
    return ans
#==============================================================================
def maxRot( farben ):
    q   = rton = -1
    ans = ''
    for farbe in farben:
        if min( [ s in '#0123456789abcdef' for s in farbe.lower() ] ) == True:
            # farbe='#012345'
            r = float( eval( '0x%s'%farbe[ 1:3 ] ) )
            g = float( eval( '0x%s'%farbe[ 3:5 ] ) )
            b = float( eval( '0x%s'%farbe[ 5:7 ] ) )
            if g + b == 0:
                if r != 0 and r > rton:
                    rton = farbe
            else:
                s = r/( g + b )
                if s > q:
                    q = s
                    ans = farbe
    if rton > -1:
        ans = rton
    return ans
#==============================================================================
class XpmDatei( file ):
    'eine Xpm-Datei'
    ASCII = ( '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
              + '!#$%&()*+,-./:;<=>?@[\\]^_{|}~' )
    #--------------------------------------------------------------------------
    def __init__( self, name, mode ):
        '''attribute von file:
        close, closed, encoding, errors, fileno, flush, isatty, mode,
        name, newlines, next, read, readinto, readline, readlines,
        seek, softspace, tell, truncate, write, writelines, xreadlines'''
        file.__init__( self, name, mode )
        self.N = len( self.ASCII )
        self.ndim = 0 # laenge des colorcode einer farbe, siehe header
        self.format = self.farben = self.pixel = self.farbcodes = self.codemap = None
    #--------------------------------------------------------------------------
    def getImage( self ):
        'gibt format, farben und pixel dieses bildes'
        ( farben, pixel, zeilen ) = [ [], [], [] ]
        inhalt = self.readlines()
        if not 'XPM' in inhalt[ 0 ].upper():
            raise Exception, '%s ist keine xpm-datei'%self.name
        # kommentare entfernen
        for zeile in inhalt:
            if zeile.strip().startswith( '"' ):
                zeilen.append( zeile.split( '"' )[ 1 ] )
        # format lesen
        nfmt = j = -1
        for zeile in zeilen:
            j += 1
            try:
                ( nrow, nlin, ncol, ndim ) = format = map(
                    int, zeile.split() )
                self.ndim = ndim
                nfmt = j
                break
            except:
                pass
        else:
            raise Exception, 'keine zeile mit 4 zahlen in %s gefunden!'%self.name
        ndef  = nfmt + 1 # beginn der farbdefinitionen
        ( farbe, codemap ) = ( {}, {} )
        j     = -1
        for zeile in zeilen[ ndef: ndef + ncol ]:
            j += 1
            code = zeile[ : ndim ]
            fhex = zeile[ ndim +3: ]
            codemap[ fhex ] = code
            farben.append( zeile.split()[ -1 ] )
            farbe[ code ] = j
            #print 'farbe >%s<'%zeile, ( code, j )
        #print 'farben=', farben
        #print 'farbe=', farbe
        npix = ndef + ncol + 1
        for code in zeilen[ npix: npix + nrow ]:
            pixel.append(
                [ farbe[ code[ n: n+ndim ] ]
                  for n in range( 0, len( code ), ndim ) ] )
        ( self.format, self.farben, self.pixel, self.farbcodes, self.codemap ) = (
            format, farben, pixel, farbe, codemap )
        return ( format, farben, pixel )
    #--------------------------------------------------------------------------
    def setImage( self, f, par, b=200, h=200, n=100, np=0 ):
        'erstellt bild mit n farben gemaess f( i=0..b,j=0..h,*par )'
        pix  = [ b*[ 0 ] for j in h*[ 0 ] ]
        fmin = 1.e34
        fmax = -fmin
        for i in range( h ):
            for j in range( b ):
                pix[ i ][ j ] = fij = f( i, j, *par )
                fmin = min( fij, fmin )
                fmax = max( fij, fmax )
        # normalisieren auf 0:n
        df   = fmax - fmin
        pmin = 1.e34
        pmax = -pmin
        for i in range( h ):
            for j in range( b ):
                pix[ i ][ j ] = pij = int( ( pix[ i ][ j ] - fmin )/df*n )
                pmin = min( pij, pmin )
                pmax = max( pij, pmax )
        #print 'setImage', ( fmin, fmax ), ( pmin, pmax ), n
        #self.makeXpm( getFarben( n, np ), pix )
        return ( getFarben( n, np ), pix )
    #--------------------------------------------------------------------------
    def makeXpm( self, farben, pixel ):
        '''gibt das xpm-Bild mit farben im rgb-Format
        pixel ist list aus list mit eintraegen 0 <= int < len( farben )'''
        img = self.header( farben, pixel )
        img += self.palette( farben )
        for codes in pixel:
            zeile = '"'
            for n in codes:
                zeile += self.getChr( n )
            img += zeile + '",\n'
        self.write( img + '};\n' )
    #--------------------------------------------------------------------------
    def header( self, farben, pixel ):
        'gbit die bildinformationen'
        nlin = len( pixel )      # anzahl zeilen des bildes
        nrow = len( pixel[ 0 ] ) # anzahl spalten des bildes
        ncol = j = len( farben ) # anzahl farben des bildes
        self.ndim = 0            # laenge des colorcode einer farbe
        while j > 0:
            j /= self.N
            self.ndim += 1
        return '/* XPM */\nstatic char *bild[] = {\n"%d %d %d %d",\n'%(
            nrow, nlin, ncol, self.ndim )
    #--------------------------------------------------------------------------
    def palette( self, farben ):
        'gibt die farbdefinitionen'
        ans = ''
        fmt = '"%%%ds c %%s",\n'%self.ndim
        for n in range( len( farben ) ):
            ans += fmt%( self.getChr( n ), farben[ n ] )
        return ans
    #--------------------------------------------------------------------------
    def getChr( self, n ):
        'gibt einen self.ndim langen colorcode der n-ten farbe'
        ans = self.ndim*[ ' ' ]
        j = 0
        while n > 0:
            ans[ j ] = self.ASCII[ n%self.N ]
            n /= self.N
            j += 1
        return ''.join( ans )
    #--------------------------------------------------------------------------
#==============================================================================
class PixelCleaner:
    '''gibt pixeln, die zu drei seiten von derselben farbe benachbart sind,
    diese farbe'''
    MAXITER=10
    #--------------------------------------------------------------------------
    def __init__( self, name, farben, pixel ):
        'farben, pixel sind die beiden letzten werte von XpmDatei.getImage()'
        iter = 0
        while self.getNb( pixel ):
            iter += 1
            if iter > self.MAXITER:
                break
        self.writeXpm( name, farben, pixel )
    #-------------------------------------------------------------------------
    def writeXpm( self, name, farben, pixel ):
        'schreibt XpmDatei'
        img = XpmDatei( name, 'w' )
        img.makeXpm( farben, pixel )
        img.close()
    #--------------------------------------------------------------------------
    def getNb( self, pixel ):
        'ermittelt isolierte pixel'
        neu    = []
        line   = []
        vorher = []
        ll = len( pixel[ 0 ] )
        j0 = -2
        for nachher in pixel:
            j0 += 1
            if j0 >= 0:
                for j1 in range( ll ):
                    self.check( j0, j1, ll, vorher, line, nachher, neu )
            vorher = line
            line   = nachher
        j0 += 1
        for j1 in range( ll ):
            self.check( j0, j1, ll, vorher, line, [], neu )
        return self.aendern( pixel, neu )
    #--------------------------------------------------------------------------
    def aendern( self, pixel, neu ):
        print '%d pixel werden veraendert'%len( neu )
        for ( j0,j1,j ) in neu:
            #print ( j0,j1,j )
            pixel[ j0 ][ j1 ] = j
        return len( neu ) > 0
    #--------------------------------------------------------------------------
    def check( self, j0, j1, ll, vorher, line, nachher, neu ):
        'erkennt isolierte pixel'
        nbor = []
        if len( line ) == ll:
            if j1 > 0:
                nbor.append( line[ j1-1 ] )
            if j1+1 < ll:
                nbor.append( line[ j1+1 ] )
        if len( vorher ) == ll:
            nbor.append( vorher[ j1 ] )
        if len( nachher ) == ll:
            nbor.append( nachher[ j1 ] )
        ln = len( nbor )
        if ln >= 3:
            for j in nbor:
                if nbor.count( j ) > ln - 2:
                    if line[ j1 ] != j:
                        neu.append( ( j0,j1,j ) )
                    break
    #--------------------------------------------------------------------------
#==============================================================================
class Str2img:
    'erstellt xpm-bild mit text'
    NLIN = 16
    WEISS = tuple( NLIN*[ 1 ] )
    SPC = { '+': 'plus', '-': 'minus', '_': 'unter', '.': 'punkt' }
    B2H = { # 16x16 pixel
   'fragezeichen': # ?, fuer unerkannte zeichen
       '0x1fffffffffe3ffddfffdfff9fff3fff7fff7fffffff7fff7fffffffffffffffff',
   'punkt': # .
       '0x1ffffffffffffffffffffffffffffffffffffffffffffff7fffffffffffffffff',
   'plus': # +
       '0x1ffffffffffffff7fff7fff7fff7ff007ff7fff7fff7fff7fffffffffffffffff',
   'minus': # -
       '0x1fffffffffffffffffffffffffffffffffc3fffffffffffffffffffffffffffff',
   'unter': # _
       '0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffff80fffff',
   'a': '0x1fffffffffffffffffc3ffbdfffdffc1ffbdffbdffb9ffc5fffffffffffffffff',
   'b': '0x1fffffbfffbfffbfffa3ff9dffbeffbeffbeffbeff9dffa3fffffffffffffffff',
   'c': '0x1fffffffffffffffffe3ffddffbfffbfffbfffbfffddffe3fffffffffffffffff',
   'd': '0x1ffffffefffefffeffe2ffdcffbeffbeffbeffbeffdcffe2fffffffffffffffff',
   'e': '0x1fffffffffffffffffe1ffdcffbeff80ffbfffbfffdeffe1fffffffffffffffff',
   'f': '0x1ffffff3ffefffefffc3ffefffefffefffefffefffefffeffffffffffffffffff',
   'g': '0x1fffffffffffffffffc5ffb9ff7dff7dff7dff7dffb9ffc5fffdffb9ffc3fffff',
   'h': '0x1fffff7fff7fff7fff43ff39ff7dff7dff7dff7dff7dff7dfffffffffffffffff',
   'i': '0x1fffffefffefffffffefffefffefffefffefffefffefffeffffffffffffffffff',
   'j': '0x1ffffff7fff7fffffff7fff7fff7fff7fff7fff7fff7fff7fff7fff7ffcffffff',
   'k': '0x1fffffbfffbfffbfffbdffbbffb7ff8fffafffb7ffbbffbdfffffffffffffffff',
   'l': '0x1fffffefffefffefffefffefffefffefffefffefffefffeffffffffffffffffff',
   'm': '0x1ffffffffffffffffd18fce77def7def7def7def7def7def7ffffffffffffffff',
   'n': '0x1fffffffffffffffff43ff39ff7dff7dff7dff7dff7dff7dfffffffffffffffff',
   'o': '0x1fffffffffffffffffc7ffbbff7dff7dff7dff7dffbbffc7fffffffffffffffff',
   'p': '0x1fffffffffffffffff47ff3bff7dff7dff7dff7dff3bff47ff7fff7fff7ffffff',
   'q': '0x1fffffffffffffffffc5ffb9ff7dff7dff7dff7dffb9ffc5fffdfffdfffdfffff',
   'r': '0x1fffffffffffffffffd3ffcfffdfffdfffdfffdfffdfffdffffffffffffffffff',
   's': '0x1fffffffffffffffffc3ffbdffbfff8ffff1fffdffbdffc3fffffffffffffffff',
   't': '0x1fffffffffdfffdfff83ffdfffdfffdfffdfffdfffdfffe3fffffffffffffffff',
   'u': '0x1fffffffffffffffff7dff7dff7dff7dff7dff7dff39ff85fffffffffffffffff',
   'v': '0x1fffffffffffffffff7dff7dffbbffbbffbbffd7ffd7ffeffffffffffffffffff',
   'w': '0x1ffffffffffffffffeeefeeefeeeff55ff55ff55ffbbffbbfffffffffffffffff',
   'x': '0x1fffffffffffffffff7dffbbffd7ffefffefffd7ffbbff7dfffffffffffffffff',
   'y': '0x1fffffffffffffffff7dff7dffbbffbbffd7ffd7ffefffefffefffdfff3ffffff',
   'z': '0x1fffffffffffffffff03fffbfff7ffefffdfffbfff7fff03fffffffffffffffff',
   'A': '0x1fffffffffefffd7ffd7ffbbffbbffbbff01ff7dff7dfefefffffffffffffffff',
   'B': '0x1fffffffff01ff7cff7eff7cff01ff7cff7eff7eff7cff01fffffffffffffffff',
   'C': '0x1fffffffffc1ff9eff3fff7fff7fff7fff7fff3fff9effc1fffffffffffffffff',
   'D': '0x1fffffffff03ff7cff7e7f7f7f7f7f7f7f7f7f7e7f7cff03fffffffffffffffff',
   'E': '0x1fffffffff01ff7fff7fff7fff01ff7fff7fff7fff7fff01fffffffffffffffff',
   'F': '0x1fffffffff03ff7fff7fff7fff03ff7fff7fff7fff7fff7ffffffffffffffffff',
   'G': '0x1fffffffffc1ff3eff7ffefffefffef8fefeff7eff3effc1fffffffffffffffff',
   'H': '0x1fffffffff7eff7eff7eff7eff00ff7eff7eff7eff7eff7efffffffffffffffff',
   'I': '0x1fffffffffefffefffefffefffefffefffefffefffefffeffffffffffffffffff',
   'J': '0x1ffffffffff7fff7fff7fff7fff7fff7fff7fff7fff7fff7fff7fff7ffcffffff',
   'K': '0x1fffffffff7dff7bff77ff6fff1fff5fff6fff77ff7bff7dfffffffffffffffff',
   'L': '0x1fffffffffbfffbfffbfffbfffbfffbfffbfffbfffbfff81fffffffffffffffff',
   'M': '0x1ffffffffe7e7e7e7ebd7ebd7edb7edb7ee77ee77eff7eff7ffffffffffffffff',
   'N': '0x1fffffffff3eff3eff5eff6eff6eff76ff76ff7aff7cff7cfffffffffffffffff',
   'O': '0x1fffffffff83ff39fe7cfefefefefefefefefe7cff39ff83fffffffffffffffff',
   'P': '0x1fffffffff03ff79ff7dff7dff79ff03ff7fff7fff7fff7ffffffffffffffffff',
   'Q': '0x1fffffffff83ff39fe7cfefefefefefefefefe7cff39ff83fffbfffdfffffffff',
   'R': '0x1fffffffff03ff79ff7dff7dff79ff03ff79ff7dff7dff7efffffffffffffffff',
   'S': '0x1fffffffff83ff3dff7fff7fff9fffe3fffdfffdff79ff83fffffffffffffffff',
   'T': '0x1ffffffffe00ffefffefffefffefffefffefffefffefffeffffffffffffffffff',
   'U': '0x1fffffffff7eff7eff7eff7eff7eff7eff7eff7effbdffc3fffffffffffffffff',
   'V': '0x1ffffffffefeff7dff7dff7dffbbffbbffd7ffd7ffd7ffeffffffffffffffffff',
   'W': '0x1ffffffffbefbbd7bdd77dd77dd77ebafebafebafebaff7dfffffffffffffffff',
   'X': '0x1ffffffffe7cff7dffbbffd7ffefffcfffd7ffbbff7dfe7cfffffffffffffffff',
   'Y': '0x1ffffffffe7cff7dffbbffbbffd7ffefffefffefffefffeffffffffffffffffff',
   'Z': '0x1fffffffff00fffefffdfffbfff7ffefffdfffbfff7fff00fffffffffffffffff',
   # zahlen 0...9
   'n0': '0x1fffffffffc7ffbbff7dff7dff7dff7dff7dff7dffbbffc7fffffffffffffffff',
   'n1': '0x1fffffffffcfffafffefffefffefffefffefffefffefff83fffffffffffffffff',
   'n2': '0x1fffffffff87ff73fffbfffbfff3fff7ffefffdfffbfff03fffffffffffffffff',
   'n3': '0x1fffffffff83ff79fffdfffdffc3fff9fffdfffdff79ff87fffffffffffffffff',
   'n4': '0x1ffffffffff3ffebffdbffdbffbbff7bff01fffbfffbfffbfffffffffffffffff',
   'n5': '0x1fffffffff03ff7fff7fff07ff7bfffdfffdfffdff7bff87fffffffffffffffff',
   'n6': '0x1fffffffffc3ff9dff3fff7fff43ff39ff7dff7dffb9ffc3fffffffffffffffff',
   'n7': '0x1fffffffff01fffbfffbfff7fff7ffefffefffdfffdfffbffffffffffffffffff',
   'n8': '0x1fffffffff83ff39ff7dff39ffc7ff39ff7dff7dff39ff83fffffffffffffffff',
   'n9': '0x1fffffffff87ff3bff7dff7dff39ff85fffdfff9ff73ff87fffffffffffffffff',
    }
    #--------------------------------------------------------------------------
    def __init__( self, text, breite=0, hoehe=0 ):
        'erstellt xpm-datei mit schwarzem text auf weissem hintergrund'
        t2i = self.getT2i( text )
        pixel = self.getPixel( text, t2i, breite )
        self.adjust( pixel, breite, hoehe )
        self.fid = self.writeXpm( text, pixel )
    #--------------------------------------------------------------------------
    def getT2i( self, text ):
        'erstellt zeichenvorrat t2i[ zeiche ] = pixel fuer zeichen in text'
        t2i = {}
        for s in text:
            if not t2i.has_key( s ):
                if s.isdigit(): # 0..9
                    key = 'n%s'%s
                elif self.SPC.has_key( s ):
                    key = self.SPC[ s ]
                elif self.B2H.has_key( s ):
                    key = s
                else:
                    key = 'fragezeichen'
                b = bin( eval( self.B2H[ key ] ) )[ 3: ]
                pixel = [ map( int, b[ n: n+self.NLIN ] )
                          for n in range( 0, len( b ), self.NLIN ) ]
                t2i[ s ] = self.removeWhite( pixel )
        return t2i
    #--------------------------------------------------------------------------
    def removeWhite( self, array ):
        'entfernt weisse spalten'
        pixel = zip( *array )
        while 1:
            z = pixel.pop()
            if z != self.WEISS:
                pixel.extend( [ z, self.NLIN*[ 1 ] ] )
                break
        while 1:
            z = pixel[ 0 ]
            if z == self.WEISS:
                pixel = pixel[ 1: ]
            else:
                pixel = [ self.WEISS, z ] + pixel
                break
        return zip( *pixel )
    #--------------------------------------------------------------------------
    def getPixel( self, text, t2i, breite=0 ):
        'macht pixel des textes auf breite gefuellt'
        pixel = []
        for n in range( self.NLIN ):
            zeile = []
            for s in text:
                zeile.extend( t2i[ s ][ n ] )
            if len( zeile ) < breite:
                b = ( breite - len( zeile ) )
                a = ( b/2 )*[ 1 ]
                if b%2 == 0:
                    zeile = a + zeile + a
                else:
                    zeile = a + [ 1 ] + zeile + a
            pixel.append( zeile )
        return pixel
    #--------------------------------------------------------------------------
    def adjust( self, pixel, breite, hoehe ):
        'fuellt pixel bis hoehe mit weiss auf'
        b = max( breite, len( pixel[ 0 ] ) )
        l = max( 1, hoehe/2 - self.NLIN/2, b/2 - self.NLIN/2 )
        for j in range( l ):
            pixel.insert( 0, b*[ 1 ] )
            pixel.append( b*[ 1 ] )
        if len( pixel ) != hoehe:
            pixel.append( b*[ 1 ] )
    #--------------------------------------------------------------------------
    def writeXpm( self, text, pixel ):
        'schreibt schwarz-weiss-xpm-datei'
        ( name, ext ) = os.path.splitext( text )
        fid = XpmDatei( '%s.xpm'%name, 'w' )
        fid.makeXpm( [ '#000000', '#FFFFFF' ], pixel )
        fid.close()
        print '%s geschrieben'%fid.name
        return fid
    #--------------------------------------------------------------------------
#==============================================================================
def legende( a, b, n, h=0, pix=[] ):
    '''erstellt legende mit n farben
           r g b
    rot   ff0000 b 
    gelb  ffff00 0.25*a + 0.75*b
    gruen 00ff00 0.75*a + 0.25*b
    cyan  008080 0.875*a + 0.125*b
    blau  0000ff a
    '''
    #--------------------------------------------------------------------------
    def linear( x0, y0, x1, y1, x ):
        '( x - x0 )/( y - y0 ) = ( x1 - x0 )/( y1 - y0 )'
        return -( ( x0 - x )*y1 + ( x - x1 )*y0 )/( x1 - x0 )
    #--------------------------------------------------------------------------
    grau = '#ebebeb'
    leg  = [ '#ffffff', '#000000', grau ]
    balken = [ ( b, ( 255, 0, 0 ) ),                   # rot
               ( ( 1*a + 7*b )/8, ( 255, 200,   0 ) ), # orange
               ( ( 2*a + 6*b )/8, ( 255, 255,   0 ) ), # gelb
               ( ( 3*a + 5*b )/8, ( 200, 255,   0 ) ), # hellgruen
               ( ( 4*a + 4*b )/8, (   0, 255,   0 ) ), # gruen
               ( ( 5*a + 3*b )/8, (   0, 245,  84 ) ), # dunkelgruen
               ( ( 6*a + 2*b )/8, (   0, 200, 200 ) ), # cyan
               ( ( 7*a + 1*b )/8, (   0, 109, 255 ) ), # hellblau
               ( a, ( 0, 0, 255 ) ) ]                  # blau
    ( x0, ( r0, g0, B0 ) ) = balken.pop()
    ( x1, ( r1, g1, B1 ) ) = balken.pop()
    for j in range( n ):
        x = a + j*( b - a )/( n - 1 )
        if x > x1 and balken:
            ( x0, ( r0, g0, B0 ) ) = ( x1, ( r1, g1, B1 ) )
            ( x1, ( r1, g1, B1 ) ) = balken.pop()
        r = int( linear( x0, r0, x1, r1, x ) )
        g = int( linear( x0, g0, x1, g1, x ) )
        B = int( linear( x0, B0, x1, B1, x ) )
        leg.append( '#%s%s%s'%( hex( r )[2:].rjust( 2, '0' ),
                                hex( g )[2:].rjust( 2, '0' ),
                                hex( B )[2:].rjust( 2, '0' ) ) )
    if pix:
        for zeile in pix[ -h: ]:
            l  = len( zeile )/2
            m0 = l - n/2
            for m in range( 3, 3 + n ):
                if ( m - 3 )%( n/10 ) == 0 or m == 2 + n:
                    zeile[ m0 + m ] = 1
                else:
                    zeile[ m0 + m ] = m
    return leg
#==============================================================================
def getFarben( n, a=0, b=100, np=0 ):
    if np:
        leg = getFarben1( n, a, b )
    else:
        leg = getFarben0( n, a, b ) # umgekehrt
    return leg
#==============================================================================
def getFarben0( n, a=0, b=100 ):
    '''gibt n farben
           r g b
    rot   ff0000 b 
    gelb  ffff00 0.25*a + 0.75*b
    gruen 00ff00 0.75*a + 0.25*b
    cyan  008080 0.875*a + 0.125*b
    blau  0000ff a
    '''
    #--------------------------------------------------------------------------
    def linear( x0, y0, x1, y1, x ):
        '( x - x0 )/( y - y0 ) = ( x1 - x0 )/( y1 - y0 )'
        return -( ( x0 - x )*y1 + ( x - x1 )*y0 )/( x1 - x0 )
    #--------------------------------------------------------------------------
    grau = '#ebebeb'
    leg  = [ '#ffffff', '#000000', grau ]
    balken = [ (               b,  ( 128, 0, 0 ) ),     # schwarzrot
               ( ( 1*a + 9*b )/10, ( 255, 0, 0 ) ),     # rot        
               ( ( 2*a + 8*b )/10, ( 255, 200,   0 ) ), # orange
               ( ( 3*a + 7*b )/10, ( 255, 255,   0 ) ), # gelb
               ( ( 4*a + 6*b )/10, ( 200, 255,   0 ) ), # hellgruen
               ( ( 5*a + 5*b )/10, (   0, 255,   0 ) ), # gruen
               ( ( 6*a + 4*b )/10, (   0, 245,  84 ) ), # dunkelgruen
               ( ( 7*a + 3*b )/10, (   0, 200, 200 ) ), # cyan
               ( ( 8*a + 2*b )/10, (   0, 109, 255 ) ), # hellblau
               ( ( 9*a + 1*b )/10, ( 0, 0, 255 ) ),     # blau       
               (                a, ( 0, 0, 128 ) )    ] # schwarzblau
    ( x0, ( r0, g0, B0 ) ) = balken.pop()
    ( x1, ( r1, g1, B1 ) ) = balken.pop()
    for j in range( n ):
        x = a + j*( b - a )/( n - 1 )
        if x > x1 and balken:
            ( x0, ( r0, g0, B0 ) ) = ( x1, ( r1, g1, B1 ) )
            ( x1, ( r1, g1, B1 ) ) = balken.pop()
        r = int( linear( x0, r0, x1, r1, x ) )
        g = int( linear( x0, g0, x1, g1, x ) )
        B = int( linear( x0, B0, x1, B1, x ) )
        leg.append( '#%s%s%s'%( hex( r )[2:].rjust( 2, '0' ),
                                hex( g )[2:].rjust( 2, '0' ),
                                hex( B )[2:].rjust( 2, '0' ) ) )
    return leg
#==============================================================================
def getFarben1( n, a=0, b=100 ):
    '''gibt n farben
           r g b
    rot   ff0000 b 
    gelb  ffff00 0.25*a + 0.75*b
    gruen 00ff00 0.75*a + 0.25*b
    cyan  008080 0.875*a + 0.125*b
    blau  0000ff a
    '''
    #--------------------------------------------------------------------------
    def linear( x0, y0, x1, y1, x ):
        '( x - x0 )/( y - y0 ) = ( x1 - x0 )/( y1 - y0 )'
        return -( ( x0 - x )*y1 + ( x - x1 )*y0 )/( x1 - x0 )
    #--------------------------------------------------------------------------
    grau = '#ebebeb'
    leg  = [ '#ffffff', '#000000', grau ]
    balken = [ (                b, ( 0, 0, 128 ) ),     # schwarzblau       
               ( ( 1*a + 9*b )/10, ( 0, 0, 255 ) ),     # blau       
               ( ( 2*a + 8*b )/10, (   0, 109, 255 ) ), # hellblau   
               ( ( 3*a + 7*b )/10, (   0, 200, 200 ) ), # cyan       
               ( ( 4*a + 6*b )/10, (   0, 245,  84 ) ), # dunkelgruen
               ( ( 5*a + 5*b )/10, (   0, 255,   0 ) ), # gruen      
               ( ( 6*a + 4*b )/10, ( 200, 255,   0 ) ), # hellgruen  
               ( ( 7*a + 3*b )/10, ( 255, 255,   0 ) ), # gelb       
               ( ( 8*a + 2*b )/10, ( 255, 200,   0 ) ), # orange     
               ( ( 9*a + 1*b )/10, ( 255, 0, 0 ) ),     # rot        
               (                a, ( 128, 0, 0 ) )     ]# schwarzrot        
    ( x0, ( r0, g0, B0 ) ) = balken.pop()
    ( x1, ( r1, g1, B1 ) ) = balken.pop()
    for j in range( n ):
        x = a + j*( b - a )/( n - 1 )
        if x > x1 and balken:
            ( x0, ( r0, g0, B0 ) ) = ( x1, ( r1, g1, B1 ) )
            ( x1, ( r1, g1, B1 ) ) = balken.pop()
        r = int( linear( x0, r0, x1, r1, x ) )
        g = int( linear( x0, g0, x1, g1, x ) )
        B = int( linear( x0, B0, x1, B1, x ) )
        leg.append( '#%s%s%s'%( hex( r )[2:].rjust( 2, '0' ),
                                hex( g )[2:].rjust( 2, '0' ),
                                hex( B )[2:].rjust( 2, '0' ) ) )
    return leg
#==============================================================================