#!/usr/bin/python # a little bit of python intended to be used to mash plaintext UPR files (just one fractal per file atm) to do such things as : # # generate any number of inbetween layers for all the layers found in the input UPR (so far only interpolating 2 layers is roughly supported) # generate layer sets with specified opacity levels ( and ramping, eventually ) # generate layer stacks with alternating layermode chains # generate sets of layers with specified parameters randomized in a range # # but of course not guaranteed to do anything specific at all!! :P # ie it's not my problem if it breaks your stuff!! The uprs it creates can request a lot of computer resources!! beware!! ':D use at your own risk # # dan wills - for fractal fun, October 2006 danw@rsp.com.au # # done: # * auto generation of BG layer # prob kinda went away because of allowing layers underneath the interp layers # * background-is-special flag.. either change it or not.. # done (-b flag) # * mergemode alternation patterns # done, multiple -m flags allows alternation # * opacity ramp in/out # done with float ramp length parameter eg ( 0.0 - 1.0 ) to cover 0 to all of interp range # * set the new fractalname from the output filename # done # * minimal initial tkinter gui # done # todo/notes: # complex interpolation around both sides of a circle in the complex plane # nice loops and spirals of smoothly noisey complex plane interpolation / traversal # randomization of specified parameters, ramping in/out of opacities # # auto balancing of opacities # # multi-layer interpolations with nice gradient controls # fix up file reader so that it can read 1 named fractal from the main upr file, ie instant availability once written in UF # a gui, with copy-to-clipboard capability and visualisation of the interpolations # animation mode? it does kinda suggest itself.. tho this is mainly a still image project so far # grad interpolation is broken.. seems that rotation of the grad actually reorders the keys - need special interpolator for that tag # float/int detection is not perfect.. some things can still break the resulting UPR (eg floats interpolated as ints, or floats where its illegal in the UPR) # clean up all the prints - debug level it # import os, sys, getopt, time, curses, re, copy from Tkinter import * class uprMashWindow( Frame ): outTextField = None doMashButton = None saveMashButton = None uprMashGlobals = None uprMashParse = None layerScale = None opacScale = None opacRampLengthScale = None inFileField = None outFileField = None layerModesField = None textXScroll = None textYScroll = None forceOverwriteCheckbox = None forceOverwriteCheckboxVar = 0 verboseCheckbox = None verboseCheckboxVar = 0 ignoreBGCheckbox = None ignoreBGCheckboxVar = 0 iconButton = None def doMash( self ): #print "here goes! ..." #print( "key is: " + str( key ) ) #clear output field self.outTextField.delete( "1.0", END ) inFileNameStr = str( self.inFileField.get( "1.0", END) ).strip() self.uprMashGlobals.setInFileName( inFileNameStr ) outFileNameStr = str( self.outFileField.get( "1.0", END) ).strip() self.uprMashGlobals.setOutFileName( outFileNameStr ) layerint = int( self.layerScale.get() ) self.uprMashGlobals.numExtraLayers = layerint opacint = int( self.opacScale.get() ) self.uprMashGlobals.newLayerOpacity = opacint layerModesList = self.layerModesField.get( "1.0", END ).split(",") #print( "got layermodesList: " + str( layerModesList ) ) for lm in range( len( layerModesList ) ) : layerModesList[ lm ] = layerModesList[ lm ].strip() #print( "got STRIPPED layermodesList: " + str( layerModesList ) ) self.uprMashGlobals.newLayerMode = layerModesList verb = self.verboseCheckboxVar.get() if verb : self.uprMashGlobals.verboseMode = True else : self.uprMashGlobals.verboseMode = False igbg = self.ignoreBGCheckboxVar.get() if igbg : self.uprMashGlobals.ignoreBG = True else : self.uprMashGlobals.ignoreBG = False force = self.forceOverwriteCheckboxVar.get() if force : self.uprMashGlobals.forceOverwrite = True else : self.uprMashGlobals.forceOverwrite = False #print( "got verb state: " + str( verb ) ) opacrampfloat = float( self.opacRampLengthScale.get() ) self.uprMashGlobals.opacityRampLength = opacrampfloat #print( "inFileName widget value: " + str( self.inFileField.get( "1.0", END) ).strip() ) #print( "scale widget value: " + str( self.layerScale.get() ) ) #print( "opacrampfloat widget value: " + str( opacrampfloat ) ) self.uprMashParse = uprParse() #print( "numLayers (should be zero): " + str( len( self.uprMashParse.layers ) ) ) self.uprMashParse.loadAndParseUPRText( self.uprMashGlobals ) if self.uprMashParse.parsedOK : self.uprMashParse.addExtraLayers( self.uprMashGlobals ) mashStr = self.uprMashParse.getAsString( self.uprMashGlobals ) self.outTextField.insert( "1.0", mashStr ) return mashStr else : print( "could not parse UPR text (check file name or contents)" ) def mashAndSave( self ) : mashStr = self.doMash( ) if self.uprMashGlobals.verboseMode : print("writing UPR (if possible)..") if not self.uprMashGlobals.outFileAlreadyExists or self.uprMashGlobals.forceOverwrite : openStub = open( self.uprMashGlobals.outFileName, "w" ) if self.uprMashGlobals.verboseMode : print("got open UPR file for writing: \n" + str( openStub ) ) openStub.writelines( mashStr ) openStub.flush() if self.uprMashGlobals.verboseMode : print("wrote mashed upr file : " + str( self.uprMashGlobals.outFileName ) ) else : print("could not write UPR, does the output file already exist? if so you need to use the force flag: '-f'") def createWidgets( self ) : mainWidth = 85 scalerWidth = 512 self.QUIT = Button( self ) self.QUIT["text"] = "Exit" #self.QUIT["fg"] = "red" self.QUIT["command"] = self.quit self.QUIT.pack({"side": "left"}) self.doMashButton = Button( self ) self.doMashButton["text"] = "Mash", self.doMashButton["command"] = self.doMash self.doMashButton.pack({"side": "left"}) self.saveMashButton = Button( self ) self.saveMashButton["text"] = "Save", self.saveMashButton["command"] = self.mashAndSave self.saveMashButton.pack({"side": "left"}) #bollocks #logobmp = PhotoImage( master=self.master, data=uprMash_icon ) #self.iconButton = Button( self, image=logobmp ) #self.iconButton.pack({"side": "left"}) self.forceOverwriteCheckboxVar = IntVar() self.forceOverwriteCheckbox = Checkbutton( self, text="Overwrite", var=self.forceOverwriteCheckboxVar) if self.uprMashGlobals.forceOverwrite : self.forceOverwriteCheckbox.select() else : self.forceOverwriteCheckbox.deselect() self.forceOverwriteCheckbox.pack( {"side": "right"} ) self.verboseCheckboxVar = IntVar( ) self.verboseCheckbox = Checkbutton( self, text="Verbose", var=self.verboseCheckboxVar ) if self.uprMashGlobals.verboseMode : self.verboseCheckbox.select() else : self.verboseCheckbox.deselect() self.verboseCheckbox.pack( {"side": "right"} ) self.ignoreBGCheckboxVar = IntVar( ) self.ignoreBGCheckbox = Checkbutton( self, text="IgnoreBG", var=self.ignoreBGCheckboxVar ) if self.uprMashGlobals.ignoreBG : self.ignoreBGCheckbox.select() else : self.ignoreBGCheckbox.deselect() self.ignoreBGCheckbox.pack( {"side": "right"} ) #xscrollcommand #yscrollcommand #self.textXScroll = Scrollbar ( self, orient=HORIZONTAL ) #self.textYScroll = Scrollbar ( self, orient=VERTICAL ) #self.outTextField = Text( self, xscrollcommand=self.textXScroll.set, yscrollcommand=self.textYScroll.set ) self.outTextField = Text( self, width=mainWidth ) self.outTextField.pack( {"side": "top"} ) self.layerModesField = Text( self, height=1, width=mainWidth ) self.layerModesField.insert( "1.0", ", ".join( self.uprMashGlobals.newLayerMode ) ) self.layerModesField.pack( {"side": "bottom"} ) self.opacRampLengthScale = Scale( self, orient=HORIZONTAL, length=scalerWidth, label="opacRamp", to=1.5, resolution=0.001 ) self.opacRampLengthScale.set( self.uprMashGlobals.opacityRampLength ) self.opacRampLengthScale.pack({"side": "bottom"}) self.opacScale = Scale( self, orient=HORIZONTAL, length=scalerWidth, label="opacity", to=150 ) self.opacScale.set( self.uprMashGlobals.newLayerOpacity ) self.opacScale.pack({"side": "bottom"}) self.layerScale = Scale( self, orient=HORIZONTAL, length=scalerWidth, label="layers", to=320 ) self.layerScale.set( self.uprMashGlobals.numExtraLayers ) self.layerScale.pack({"side": "bottom"}) self.outFileField = Text( self, height=1, width=mainWidth ) self.outFileField.insert( "1.0", self.uprMashGlobals.outFileName ) self.outFileField.pack( {"side": "bottom"} ) self.inFileField = Text( self, height=1, width=mainWidth ) self.inFileField.insert( "1.0", self.uprMashGlobals.inFileName ) self.inFileField.pack( {"side": "bottom"} ) def __init__( self, master, uprGlobals ) : self.uprMashGlobals = uprGlobals Frame.__init__(self, master) self.pack() #self.entrythingy = Entry() #self.entrythingy.pack() #self.entrythingy.bind( '', self.doMash ) self.createWidgets() #this has now become some fairly exceedingly dumbass usage of classes and whatnot.. oh never mind! :D this script is pure hackery #little helper for visualising float values with stars def getFloatAsStarsStr( floatValue, starWhitePoint, numStarsAtWhitePoint ) : scaledFloat = floatValue if starWhitePoint != 0 : scaledFloat = scaledFloat / starWhitePoint scaledFloat = min( 1.0, max( 0.0, scaledFloat ) ) numStars = int( scaledFloat * numStarsAtWhitePoint ) star = "*" * numStars return star def getIntAsStarsStr( intValue, maxStars ) : numStars = int( max(0, min( maxStars, intValue ) ) ) star = "*" * numStars return star # ufLayerTagValue - a very basic class to hold and interpolate the values of upr file tags class ufLayerTagValue : tagValue = "" parsedOK = False def __init__( self, globals ) : self.tagValue = "" parsedOK = False def setTagValue( self, withString, globals ) : if withString : paramValues = withString self.parsedOK = True self.tagValue = withString def isValid( self ) : return self.parsedOK def getAsString( self, globals ) : return self.tagValue def getInterpolatedTagValue( self, targetTagValue, blendAmount, globals ) : #print("interpolating tag value: " + str( targetTagValue.getAsString( globals ) ) ) newTagValue = ufLayerTagValue( globals ) thisTagValue = self.tagValue intCheck = re.compile("-{0,1}([0-9]+)(?!.)").match( thisTagValue ) floatCheck = re.compile("(-{0,1}[0-9]*\.[0-9]+)").match( thisTagValue ) #also atches complex twice if globals.debugMode : print( "intCheck: " + str( intCheck ) ) print( "floatCheck: " + str( floatCheck ) ) if targetTagValue : targetValueString = targetTagValue.tagValue targetSlashSplit = targetValueString.split("/") tagSlashSplit = thisTagValue.split("/") if thisTagValue[0] == '"' and thisTagValue[-1] == '"' : #it's a string, cant really interpolate but at least we'll swap between the 2 values if blendAmount <= 0.5 : newTagValue.setTagValue( thisTagValue, globals ) else : newTagValue.setTagValue( targetValueString, globals ) #\print("looks like a string or enum to 'interpolate': " + thisTagValue ) elif len( tagSlashSplit ) == len( targetSlashSplit ) == 2 : #it's complex #then try to also split the target thisSplit = [ float( tagSlashSplit[0] ), float( tagSlashSplit[1] ) ] targetSplit = [ float( targetSlashSplit[0] ), float( targetSlashSplit[1] ) ] if thisSplit[0] != targetSplit[0] or thisSplit[1] != targetSplit[1] : interReal = (1.0 - blendAmount) * thisSplit[0] + blendAmount * targetSplit[0] interImag = (1.0 - blendAmount) * thisSplit[1] + blendAmount * targetSplit[1] newTagValue.setTagValue( str( interReal ) + "/" + str( interImag ), globals ) #print("got interpolated complex tag value: " + newTagValue.getAsString( globals ) ) # else : newTagValue.setTagValue( thisTagValue, globals ) #print("complex value did not need interpolation (it was the same at both ends): " + str( tagSlashSplit ) ) elif intCheck : doInt = True try : thisInt = int( thisTagValue ) targetInt = int( targetValueString ) except ValueError : #erk.. it gets a bit wierd but damn python makes it simple :D doInt = False thisInt = float( thisTagValue ) targetInt = float( targetValueString ) if thisInt != targetInt : #actually you can hardly ever tell when its an int rather than a truncated float.. lets just try always giving float shall we? :D if doInt : newIntFloat = int( (1.0 - blendAmount) * thisInt + blendAmount * targetInt ) else : newIntFloat = float( (1.0 - blendAmount) * thisInt + blendAmount * targetInt ) newTagValue.setTagValue( str( newIntFloat ), globals ) if globals.debugMode : print("got interpolated integer tag value: " + str( newIntFloat ) + " (" + thisTagValue + " to " + targetValueString + " by " + str( blendAmount ) + ")" ) else : if globals.debugMode : print("integer value did not need interpolation (same at both ends): " + str( thisInt ) ) newTagValue.setTagValue( thisTagValue, globals ) elif floatCheck : thisFloat = float( thisTagValue ) targetFloat = float( targetValueString ) if thisFloat != targetFloat : newFloat = (1.0 - blendAmount) * thisFloat + blendAmount * targetFloat newTagValue.setTagValue( str( newFloat ), globals ) if globals.debugMode : print("got interpolated float tag value: " + str( newFloat ) + " (" + thisTagValue + " to " + targetValueString + " by " + str( blendAmount ) + ")" ) else : if globals.debugMode : print("float value did not need interpolation (same at both ends): " + str( thisFloat ) ) newTagValue.setTagValue( thisTagValue, globals ) else : if blendAmount <= 0.5 : newTagValue.setTagValue( thisTagValue, globals ) else : newTagValue.setTagValue( targetValueString, globals ) #print("param is not complex or a string:" + str( self.tagValue ) ) #print("new tag value: " + str( newTagValue.getAsString( globals ) ) ) return newTagValue # ufLayerTagSet - essentially a set of aforementioned tags.. as in the groups in a UPR, somekinda tuple-mashing class class ufLayerTagSet: #set name, eg 'layer:', "inside:", etc tagSetName = "" # an array of tuples ( string, ufLayerTagValue ) tagSet = [] def __init__( self, name, globals ) : self.tagSetName = name self.tagSet = [] #print("created a new tag set with name: " + name ) def addTagToSet( self, name, tag ) : self.tagSet.append( ( name, tag ) ) def setWithStringList( self, tagText, globals) : #print( "setWithStringList for tag sets called: " + str( self.tagSetName ) ) self.tagSet = [] newTagSet = ufLayerTagSet( self.tagSetName, globals ) currentLine = 0 while currentLine < len( tagText ) : #print( "tagLine number is: " + str( currentLine ) ) stripLine = tagText[ currentLine ].strip() if len(stripLine) > 0 and stripLine[-1] == ":" : print ("looks like a group label.. wierd") stripWhittle = stripLine firstEquals = stripWhittle.find( "=" ) count = 0 while firstEquals > 0 and count < 150: paramName = stripWhittle[ 0 : firstEquals ] paramValue = "" # print("got first paramName: " + paramName ) if stripWhittle[ firstEquals+1 ] == '"' : afterQuote = stripWhittle[ firstEquals+2 : ] #print( "afterQuote: " + afterQuote ) stringEnd = afterQuote.find( '"' ) #print("stringEnd: " + str( stringEnd ) ) paramValue = '"' + afterQuote[ 0 : stringEnd ] + '"' stripWhittle = afterQuote[ stringEnd + 1 : ] #print( "got stringVal: " + paramValue ) else : afterEquals = stripWhittle[ firstEquals + 1 : ] # #print("afterEquals: " + afterEquals ) nextSpace = afterEquals.find( " " ) if nextSpace > 0: paramValue = afterEquals[ 0 : nextSpace ] else : paramValue = afterEquals #print( "got otherVal nextSpace: " + str( nextSpace ) + " paramVal: " + str( paramValue ) ) stripWhittle = afterEquals[ nextSpace + 1 : ] #print( "stripWhitle is now: " + stripWhittle ) #print( "paramValue: " + paramValue ) tag = ufLayerTagValue( globals ) tag.setTagValue( paramValue, globals ) if tag.isValid() : self.addTagToSet( paramName.strip(), tag ) # print ("uuiue added tag: " + paramName.strip() + " = " + tag.getAsString( globals ) ) firstEquals = stripWhittle.find( "=" ) count += 1 currentLine += 1 #self.tagSet.append( newTagSet ) def getAsString( self, globals ) : wrap = globals.wrapWidth tagString = "" if len( self.tagSet ) > 0 : firstTagTuple = self.tagSet[0] #print( "tagtest: " + str( firstTagTuple ) ) tagString = " " + firstTagTuple[0] + "=" + firstTagTuple[1].getAsString( globals ) count = 1 for tag in self.tagSet[1:] : if (count % wrap) != 0 : tagString += " " + tag[0] + "=" + tag[1].getAsString( globals ) else : tagString += "\n " + tag[0] + "=" + tag[1].getAsString( globals ) count += 1 return ( self.tagSetName +"\n" + tagString ) def getValueOfTag( self, tagName ) : #BAD !!! for tag in self.tagSet : if tagName in tag[0] : return tag[1] def setValueOfTag( self, tagName, newValue, globals ) : #BAD !!! show us yer dic tyanairy man! :P #this doesn't fail if the tag doesnt exist !! for tag in self.tagSet : if tagName in tag[0] : tag[1].setTagValue( newValue, globals ) def addAndSetValueOfTag( self, tagName, newValue, globals ) : #BAD !!! show us yer dic tyanairy man! :P foundTag = False for tag in self.tagSet : if tagName in tag[0] : tag[1].setTagValue( newValue, globals ) foundTag = True if not foundTag : newTagVal = ufLayerTagValue( globals ) newTagVal.setTagValue( newValue, globals ) self.addTagToSet( tagName, newTagVal ) def getInterpolatedTagSet( self, targetTagSet, blendAmount, layerNumber, globals ) : #need to handle the layer: 'caption' tag a bit differently.. so that we get a new layerName #nah who cares.. still works.. polish for later newTagSet = ufLayerTagSet( self.tagSetName, globals ) #l1s = str( self.tagSet ) # .getAsString( globals ) #l2s = str( targetTagSet.tagSet ) #.getAsString( globals ) #print("\n\nL1S=\n" + l1s + "\n--------------\nL2S=\n" + l2s ) #print("\n\nlenL1S=\n" + str(len(l1s)) + "\n--------------\nlenL2S=\n" + str(len(l2s)) ) #tag, blendTag in zip( self.tagSet, targetTagSet.tagSet ) for i in range( 0, len( targetTagSet.tagSet ) ) : tag = self.tagSet[ i ] blendTag = targetTagSet.tagSet[i] #print( "interpolating tag: " + str( tag[0] ) ) if tag[0] != blendTag[0] : print("WARNING: tag name mismatch, might not interpolate properly: " + str( tag[0] ) + " to " + str( blendTag[0] ) ) #else : #print("tag names match: " + str( tag[0] ) + " to " + str( blendTag[0] ) ) interTag = None if self.tagSetName == "layer:" and tag[0] == "caption" : layerName = ( "inter_" + str( layerNumber ) ) # print( "trying to interpolate the caption tag, new layername will be: " + layerName ) interTag = ufLayerTagValue( globals ) interTag.setTagValue( layerName, globals ) else : interTag = tag[1].getInterpolatedTagValue( blendTag[1], blendAmount, globals ) if interTag : newTagSet.addTagToSet( tag[0], interTag ) else : print("No good, the interpolator gave back None..") #print("got interTagSet: " + str( newTagSet.getAsString( globals ) ) ) #fingers crossed ;D return newTagSet class ufLayer : parsedOK = False #actually a list of 'ufLayerTagSet' objects tagSetList =[] isBG = False layerNumber = -1 #blank constructor, for the interpolator def __init__( self, globals, isBGLayer ) : self.parsedOK = False self.tagSetList = [] self.isBG = isBGLayer def setLayerWithStringList( self, layerText, globals, layerNum ) : self.layerNumber = layerNum #print( "\n\nlayerText is: " + str( layerText ) + "\n\n") if layerText and globals.isValid : tagSetList =[] currentLine = 1 #skip the known, 'layer' line, and start ready to grab it's params tagSet = ufLayerTagSet( "layer:", globals ) #tagSet.setWithStringList( layerText[1 : ], globals ) tagLines = [] while currentLine < len( layerText ) : stripLine = layerText[ currentLine ].strip() #print( "stripLine is: " + stripLine ) #line ends in a colon, special (screws comments tho) if stripLine[-1] == ':' : #add on last tagset if len( tagLines ) > 0 : tagSet.setWithStringList( tagLines, globals ) #print("got tagSet: \n\n" + str( tagSet.getAsString( globals ) ) + "\n\n") else : print("taglines was empty at an inopportune moment") self.tagSetList.append( tagSet ) #print("new tag for line: " + stripLine ) tagSet = ufLayerTagSet( stripLine, globals ) tagLines = [] else : tagLines.append( stripLine ) currentLine += 1 #append the last one too.. tagSet.setWithStringList( tagLines, globals ) self.tagSetList.append( tagSet ) self.parsedOK = True else : print(" layer parse parameter was invalid." ) def addTagSetList( self, tagSet, globals ) : #if tagSet and tagSet.isValid() : self.tagSetList.append( tagSet ) def getAsString( self, globals, layerNum ) : self.layerNumber = layerNum returnStr = "" #returnStr +=( "there are: " + str( len( self.tagSetList ) ) + " tagSets in this layer.\n" ) for tag in self.tagSetList : #print( "tag: " + str( tag ) ) bgTest = globals.ignoreBG and self.isBG #print( "isBG: " + str( self.isBG ) ) #print( "bgTest: " + str( bgTest ) ) if ( not globals.ignoreBG ) or not bgTest: #print ("---------tagset is: " + tag.tagSetName ) if tag.tagSetName == "layer:" : totalNumLayers = globals.numExtraLayers + globals.numExistingLayers - 1 layerOpac = globals.newLayerOpacity rampLen = int( globals.opacityRampLength * float( totalNumLayers ) ) #print("ramplen: " + str( rampLen ) ) if rampLen > 0 : opacRampUp = min( 1.0, 1.0 - float( rampLen - self.layerNumber ) / float( rampLen + 1 ) ) #print("layernum: " + str( self.layerNumber ) + " totalnum: " + str( totalNumLayers ) ) opacRampDown = min( 1.0, 1.0 - float( rampLen - ( totalNumLayers - self.layerNumber - 1 ) ) / float( rampLen + 1 ) ) finalOpac = opacRampUp * opacRampDown #if globals.verboseMode : print("opacRamp: " + getFloatAsStarsStr( finalOpac, 1.0, 60 ) ) layerOpac = max( 1, int( float( layerOpac ) * finalOpac ) + 1 ) if globals.verboseMode : if not self.isBG : print( "opac: " + getIntAsStarsStr( layerOpac, 60 ) ) #otherwise dont adjust the opac any other way yet #print( "layerOpac: " + str( layerOpac ) ) tag.setValueOfTag( "opacity", str( layerOpac ) , globals ) #go through the list that is formed.. this allows alternating layermode patterns layerNumMod = self.layerNumber % len( globals.newLayerMode ) #print( "layerNumber: " + str( self.layerNumber ) + " numModes: " + str( len( globals.newLayerMode ) ) ) if layerNumMod< 0 : layerNumMod = 0 tag.addAndSetValueOfTag( "mergemode", globals.newLayerMode[ layerNumMod ], globals ) #opacValue = tag.getValueOfTag( "opacity" ) #print( "set opacityValue: " + str( opacValue.getAsString( globals ) ) ) returnStr += tag.getAsString( globals ) + "\n" return returnStr def setLayerNumber( self, num ) : self.layerNumber = num def getInterpolatedLayer( self, interpTarget, globals, blendAmount, layerNum ) : #print( "interlayer layerNumber: " + str( layerNum ) ) # let this layer be the template for what tagSets are added to the interlayer #actually they need to be exactly the same at the moment to work.. hmm will eventualy fix that #the 'False' just says this layer is NOT the bg layer interLayer = ufLayer( globals, False ) interLayer.layerNumber = layerNum for tag, blendTag in zip( self.tagSetList, interpTarget.tagSetList ) : interLayer.addTagSetList( tag.getInterpolatedTagSet( blendTag, blendAmount, layerNum, globals ), globals ) return interLayer #this doesn't work unless there is one.. of course def getCaptionString( self ) : layerTagSet = self.tagSetList[0] return layerTagSet.getValueOfTag( "caption" ).tagValue def isValid( self ) : return self.parsedOK class uprParse : # topText - a special chunk of text for the top bit of the UPR and the 'fractal' tag # which I dont currently want to change at all.. so it will be preserved intact.. # okay I take that back, I definately do need to change the 'layers' parameter!! :P topText = [] topTagSet = None layerTags = [] parsedOK = False # an array of ufLayer layers = [] def __init__( self ) : #print("uprParse konstruktor!" ) self.layers = [] self.topText = [] self.topTagSet = None self.layerTags = [] def loadAndParseUPRText( self, globals ) : inFileName = os.path.join( globals.sourcePath, globals.inFileName ) if os.path.isfile( inFileName ) : inFileHandle = open( inFileName, "r" ) if globals.verboseMode : print("got open UPR file for reading: \n" + str( inFileHandle ) ) stringList = None if inFileHandle : stringList = inFileHandle.readlines() if globals.debugMode : print( "\ninput UPR: -------------------->" ) for f in stringList : print f.strip( "\n" ) print( "<--------------------\n" ) else : print("error opening file.. perhaps you don't have read permissions? (chmod +r)") if globals.verboseMode : print("got " + str( len( stringList ) ) + " lines from UPR file") if stringList : currentLine = 0 firstBitDone = False while not firstBitDone and currentLine < len( stringList ) : #print("currentLine is: " + str( currentLine ) ) #should cater for ignoring comment blocks here.. and selection of which fractal if there are more than one. strippedLine = stringList[ currentLine ].strip() if strippedLine != "layer:" : #don't add blank lines if len( strippedLine ) > 1 : self.topText.append( stringList[ currentLine ].strip() ) else : self.topTagSet = ufLayerTagSet( "fractal:", globals ) fracTagTextSlice = self.topText[ 2: ] #print("fracTagTextSlice is: " + str( fracTagTextSlice ) ) self.topTagSet.setWithStringList( fracTagTextSlice, globals ) if globals.verboseMode : print("got Fractal : \n\n" + self.topTagSet.getAsString( globals ) + "\n" ) firstBitDone = True currentLine += 1 #print( "got 'topBit' :\n----> " + "----> ".join( self.topText ) ) #increment to enter the layer, so we dont bail out on the first while below #currentLine += 1 layersDone = False while not layersDone and currentLine < len( stringList ) : nextLayer = False layerSet = [ "layer:\n", ] while not nextLayer and currentLine < len( stringList ): if stringList[ currentLine ].strip() == "layer:" : nextLayer = True elif stringList[ currentLine ].strip() == "}" : if globals.verboseMode : print( "end of UPR found on line: " + str( currentLine + 1 ) ) nextLayer = True layersDone = True else : layerSet.append( stringList[ currentLine ] ) currentLine += 1 #print( "got supposed layerSet: \n--------->" + "--------->".join( layerSet ) ) self.layerTags.append( layerSet ) if globals.verboseMode : print("looks like there were " + str( len( self.layerTags ) ) + " layers in that UPR" ) if globals.verboseMode : print("new UPR will contain: " + str( globals.numExtraLayers + globals.numExistingLayers ) + " layers total" ) globals.numExistingLayers = len( self.layerTags ) isLastCount = 0 for layerText in self.layerTags : #print( "\n\nlayer text: " + str( layerText ) ) #first layer is always BG I assume, nope.. actually its the last #make this take all but the first two layers as BG isBG = ( isLastCount > 1 ) #= ( len( self.layerTags ) - 1 ) ) isLastCount += 1 layerParse = ufLayer( globals, isBG ) layerNum = isLastCount - 1 if isBG : layerNum = globals.numExtraLayers + globals.numExistingLayers - 1 #print( "isBG! layerNum is: " + str( layerNum ) ) isBG = False layerParse.setLayerWithStringList( layerText, globals, layerNum ) #print( "\n\nparsed layer text: " + layerParse.getAsString( globals, isLastCount ) ) if layerParse.isValid() : self.layers.append( layerParse ) if globals.verboseMode : print( "parsed and added layer: " + str( layerParse.getCaptionString() ) + " number: " + str( isLastCount - 1 )) else : print( "could not parse layer text: " + str( layerText ) ) self.parsedOK = True else : print( "specified file does not exist: " + str( inFileName ) ) def getAsString( self, globals ) : #print("YO!-------------------------------------------") outStr = globals.outFileName outSplit = globals.outFileName.split(".") if len( outSplit ) > 1 : outStr = ".".join( outSplit[ :-1] ) result = outStr + " {\n" # self.topText[0] + "\n" self.topTagSet.setValueOfTag( "layers", str( globals.numExtraLayers + globals.numExistingLayers ) , globals ) layersValue = self.topTagSet.getValueOfTag( "layers" ) #print( "set layersValue: " + str( layersValue.getAsString( globals ) ) ) result += self.topTagSet.getAsString( globals ) + "\n" #result += "\n---\n" #print("there are " + str( len( self.layers ) ) + " layers" ) count = 0 for layer in self.layers : result += layer.getAsString( globals, count ) count += 1 #result += "\n---\n" result += "}\n" #result += "\n---\n" return result def addExtraLayers( self, globals ) : #if len( layers ) > 1 : #for i in range( 1, len( layers ) ) : rampLength = globals.numExtraLayers + 1 #print( "rampLength is: " + str( rampLength ) ) topLayer = self.layers[1] bgLayer = self.layers[0] for i in range( 1, rampLength ) : factor = float( i ) / float ( rampLength ) #print("this is the factor: " + str( factor ) ) interLayer = bgLayer.getInterpolatedLayer( topLayer , globals, factor, i ) if interLayer : self.layers.insert( len( self.layers ) - (globals.numExistingLayers - 1), interLayer ) #print("added interlayer:" + interLayer.getAsString( globals ) ) else : print("interpolated layer was None! probably a bug.. get hackin' ;P") def checkAndAddExt( filename, globals ) : if len( filename ) > 4 : extCheck = filename[ -4: ] if str.lower( extCheck ) != ".upr" : if globals.verboseMode : print( "extCheck added upr extension: " + (filename + ".upr") ) return filename + ".upr" else : return filename else : #not possible to contain the entire string anyway, so add it if globals.verboseMode : print( "extCheck added upr extension: " + (filename + ".upr") ) return filename + ".upr" class ufParaMashGlobals : helpStr = ("\n------------------------------------\n\n", "\tuprMash.py\n" "\t\tA little experiment in plaintext UPR file mashing\n", "\t\tTo help achieve various interpolation effects\n", "\t\tWritten by Dan Wills, 2006\n\n", "\tUsage:\n", "\t\tufParaMash -u inFile.upr -o outFile.upr \n\n", "\tOther Flags:\n\n", "\t\t-i or --info\n\n", "\t\t\tinfo mode :\n", "\t\t\tthis prints the UPR and some other info\n\n", "\t\t-d or --debug\n\n", "\t\t\tdebug mode :\n", "\t\t\tprint even more info\n\n", "\t\t-h or --help\n\n", "\t\t\thelp mode :\n", "\t\t\tprint what you're currently reading\n\n", "\t\t-u or --uprfile \n\n", "\t\t\tset input UPR filename :\n", "\t\t\tcan be specified without extension\n\n", "\t\t-o or --outputfile \n\n", "\t\t\tset output UPR filename :\n", "\t\t\tupr extension will be added if not specified\n\n", "\t\t-l or --layers \n\n", "\t\t\tnum layers :\n", "\t\t\tset the number of interpolating layers to generate\n\n", "\t\t-f or --force\n\n", "\t\t\toverwrite mode :\n", "\t\t\tallow overwriting existing files\n\n", "\t\t-o or --opacity\n\n", "\t\t\tset opacity :\n", "\t\t\tset the opacity of ALL layers\n\n", "\t\t-m or -layermode\n\n", "\t\t\tset layermode :\n", "\t\t\tset the layermode (mergemode) for all layers\n\n", "\t\t\tmultiple layermode flags may be specified\n", "\t\t\tand they will be cycled through accross the layers\n\n", "\t\t\teg: normal, multiply, screen, \n", "\t\t\tsoftlight, hardlight, darken, lighten, \n", "\t\t\tdifference, hue, saturation, color,\n", "\t\t\tluminance, addition, hsladd, red, green, blue\n\n", "\t\t-r or -rampopacity \n\n", "\t\t\tset length of opacity ramp:\n", "\t\t\tas a fraction of the entire range (0.0,1.0) \n" "\t\t\tfade in and out the opacity accross \n", "\t\t\tthe interpolated range (like a camera shutter)\n\n", "\t\t-g or --gui\n\n", "\t\t\tstart in gui mode (EXPERIMENTAL!)\n\n", "\t\t-b or --dobackground\n\n", "\t\t\tenable setting opacity and layermode on BG layers\n", "\n\tExample:\n\n", "\t./uprMash.py -v -f -i infile.upr -o outfile.upr\n", "\t-l 105 -p 14 -m multiply -m screen -r 0.7\n", "\n------------------------------------\n\n" ) # "outputfile=", "uprfile=","layers=","force","opacity=","layermode= sourcePath = "./" preStr = "" infoMode = False debugMode = False verboseMode = True #for the moment! inFileName = "paraMashInput" inFileLines = None outFileName = "paraMashOutput" outFileAlreadyExists = True forceOverwrite = True isValid = True #for now wrapWidth = 2 numExistingLayers = 0 numExtraLayers = 16 newLayerOpacity = 12 opacityRampLength = 0.8 ready = False newLayerMode = [ ] ignoreBG = True guiMode= False def setInFileName( self, fname ) : fname = checkAndAddExt( fname, self ) try: if fname and os.path.isfile( fname ) : if self.verboseMode : print( "got valid inFileName: " + str( fname ) ) self.inFileName = fname self.ready = True else : print("looks like an invalid input filename was specified... please make sure the file is definately there and that you have permissions to read it.") self.inFileName = "Standard Input" except : print("\n!!!!!!\nerror opening file: " + str( fname ) + " perhaps you don't have read permissions? (chmod +r)\n") def setOutFileName( self, fname ) : if fname : fname = checkAndAddExt( fname, self ) if os.path.isdir( fname ) : if __self.verboseMode : print( "output file is a directory, wierd.. don't write anything? or write to the inFileName in the dir?" ) print("checking if the infilename: " + str(self.inFileName) + " exists in the dir..") self.outFileName = os.path.join( fname, self.inFileName ) if os.path.isfile( self.outFileName ) : self.outFileAlreadyExists = True else : self.outFileAlreadyExists = False elif os.path.isfile( fname ) : if self.verboseMode : print( "output file already exists! no output will be written unless in force mode!" ) self.outFileName = fname self.outFileAlreadyExists = True else : self.outFileName = fname self.outFileAlreadyExists = False if self.verboseMode : print( "outFile does not exist: " + str( fname ) ) else : print("filename specified to setOutFileName was None!") def usage() : paraMash = ufParaMashGlobals() print str( "".join( paraMash.helpStr ) ) def main( ) : try: #force overwrite mode opts, args = getopt.getopt(sys.argv[1:], "idvho:u:l:fp:m:r:bg", [ "info", "debug", "verbose", "help", "outputfile=", "uprfile=","layers=","force","opacity=","layermode=","rampopacity=","dobackground", "gui"]) except getopt.GetoptError: # print help information and exit: usage() sys.exit(2) verbose = False paraMash = ufParaMashGlobals() parseObject = uprParse() configText = None for o, a in opts: if o in ("-v", "--verbose"): paraMash.verboseMode = True verbose = True print( paraMash.preStr + "verbosity is ON" ) if o in ("-i", "--info"): if verbose : print( paraMash.preStr + "info mode ON") paraMash.infoMode = True if o in ["-h", "--help"] : usage() if o in ["-u", "--uprfile"] : if a : paraMash.setInFileName( a ) if verbose : print( paraMash.preStr + "got input uprFileName: " + paraMash.inFileName ) elif verbose : print "-u or --uprfile flag specified but no input filename given!" if o in ["-l","--layers"] : if a: paraMash.numExtraLayers = int( a ) if verbose : print( paraMash.preStr + "got number of extra layers: " + str( paraMash.numExtraLayers ) ) elif verbose : print "-l or --layers flag specified but no parameter given!" if o in ["-p","--opacity"] : if a: paraMash.newLayerOpacity = int( a ) if verbose : print( paraMash.preStr + "got opacity of extra layers: " + str( paraMash.newLayerOpacity ) ) else : print "-p or --opacity flag specified but no parameter given!" usage() exit() if o in ["-r","--rampopacity"] : if a: paraMash.opacityRampLength = float( a ) if verbose : print( paraMash.preStr + "got opacity ramp length: " + str( paraMash.opacityRampLength ) ) else : print "-r or --rampopacity flag specified but no parameter given!" usage() exit() if o in ["-m","--layermode"] : if a: paraMash.newLayerMode.append( a ) if verbose : print( paraMash.preStr + "got layermode of extra layers: " + str( paraMash.newLayerMode ) ) else : # now an initialised member: paraMash.newLayerMode = "normal" print "-m or --layermode flag specified but no parameter given!" usage() exit() if o in ["-o", "--outputfile"] : if a : paraMash.setOutFileName( a ) if verbose : print( paraMash.preStr + "got output uprFileName: " + paraMash.outFileName ) else : print "-o flag specified but no output filename given!" usage() exit() if o in [ "-f", "--force" ] : if verbose : print "force overwrite mode ON" paraMash.forceOverwrite = True if o in [ "-b", "--dobackground" ] : if verbose : print "Do background mode ON" paraMash.ignoreBG = False if o in [ "-g", "-gui" ] : if verbose : print "gui mode ON" paraMash.guiMode = True if len( opts ) == 0 : print("no args, going into gui mode..") paraMash.guiMode = True if len( paraMash.newLayerMode ) == 0 : paraMash.newLayerMode.append( "normal" ) if not paraMash.guiMode : try : if paraMash.ready : if paraMash.verboseMode : print("loading and parsing UPR file...") parseObject.loadAndParseUPRText( paraMash ) if parseObject.parsedOK : if paraMash.verboseMode : print("adding interpolated layers..") parseObject.addExtraLayers( paraMash ) if paraMash.verboseMode : print("getting new UPR as a string..") print("opacity scale is: " + str( paraMash.newLayerOpacity ) ) fullStr = parseObject.getAsString( paraMash ) if paraMash.verboseMode : print("writing UPR (if possible)..") if not paraMash.outFileAlreadyExists or paraMash.forceOverwrite : openStub = open( paraMash.outFileName, "w" ) if paraMash.verboseMode : print("got open UPR file for writing: \n" + str( openStub ) ) openStub.writelines( fullStr ) openStub.flush() print("wrote mashed upr file : " + str( paraMash.outFileName ) ) else : print("could not write UPR, does the output file already exist? if so you need to use the force flag: '-f'") if paraMash.infoMode : print("full str:\n---------------------8<--------------------" ) print( fullStr + "--------------------->8--------------------\n") else : print( "could not parse inputFile for some reason.." ) else : if paraMash.verboseMode : print( "it appears that something is not ready.. please check the inputfile flag is correct: [ -u filename.upr ]") except KeyboardInterrupt : print( "UPR parse interrupted by user" ) else : print( "it appears that we're going into gui mode..") root = Tk() iconName = 'uprMash_icon_64.ico' if os.path.isfile( iconName ) : root.iconbitmap( iconName ) else : print("Could not see window icon file: " + iconName ) app = uprMashWindow( root, paraMash ) app.master.title("uprMash") #logobmp = PhotoImage(file='uprMash_icon.bmp',format='bmp') #app.wm_iconbitmap( "@uprMash_icon.bmp" ) #app.master.iconbitmap( "uprMash_icon_32.gif" ) try : app.mainloop() except KeyboardInterrupt : print( "uprMash GUI interrupted by user" ) #root.destroy() #if no upr found in params, find all uprs in current dir? #if no output name, add "_inter" to the input filename if __name__ == '__main__': main( )