#!/var/lib/install/usr/bin/python2.4 import glob, os, sys, pygame, Image, time, math, ImageEnhance, pickle from pygame.locals import * #need this for 'FULLSCREEN' value class Urban(object): """Class for urbanhermes. <3 EDIT FOR OTHER: remotehost, outRequest EXPERIMENT EDIT: imagedirectory! outRequest (at end!) """ def __init__(self, imageList = [], width = 800, height = 480, imagedirectory = '/media/mmc1/', remoteuser = 'root', remotehost = '10.0.0.2', remotedirectory = '/home/user/MyDocs/.images', outRequest = '/home/user/MyDocs/.images/momo.request', name = 'name'): """Initialize, setup, prepare the screen""" pygame.init() pygame.mouse.set_visible(False) self.size = (width, height) self.width = width self.height = height self.left = 0 self.top = 0 self.white = (255,255,255) self.teal = (13, 214, 174) self.pink = (255,0,183) self.black = (0,0,0) self.backgroundcolor = self.black self.screen = pygame.display.set_mode(self.size, FULLSCREEN) self.screenRect = Rect(self.left, self.top, self.width, self.height) # DRAW SPLASH SCREEN self.fontpath = '/var/lib/install/usr/lib/python2.4/site-packages/pygame/' self.defaultfont = self.fontpath + pygame.font.get_default_font () self.titlefont = pygame.font.Font(self.defaultfont, 50) self.screen.fill(self.pink) self.screen.blit(self.titlefont.render('urbanhermes', True, (255,255,255)), self.screen.get_rect().move(40,40)) pygame.display.flip() # MANAGE INVENTORY OF IMAGES self.imageList = imageList # HOLDS IMAGE SURFACES self.fileList = [] # HOLDS FILENAMES (strings) self.rectList = [] self.numFiles = 0 self.numFilesMax = 10 # SPECIFYING IMAGE ON DISPLAY self.currImage = 0 self.currRect = 0 self.imageIndex = 0 # EXPIRATION self.expirytime = 14400 # in seconds, 14400 = 4 hours # DEGRADATION self.enhancefactor = 0.75 # fade to black 75% with each mod # FILE TRANSFER STUFF self.imagedirectory = imagedirectory self.remoteuser = remoteuser self.remotehost = remotehost self.remotedirectory = remotedirectory self.outRequest = outRequest # MAKE SURE REQUESTS ARE CLEAN strayRequests = glob.glob (self.imagedirectory + '*.request') if len(strayRequests) > 0: for index in range (len (strayRequests)): os.remove(strayRequests[index]) # MAKE INDIVIDUAL REQUEST FILE WITH EMBEDDED PROFILE profile = {'name': name, 'website': name + ".com"} requestfile = open (self.outRequest, 'w') # requestfile.write ('yay') pickle.dump (profile, requestfile) # EMBED requestfile.close() self.history = [] self.historymax = 5 # STORE LAST RECENT N TRANSACTIONS self.downloadFlag = False # MAKE SOUND OBJECT FOR ALERT BEEPS self.beepalert = pygame.mixer.Sound('/home/user/MyDocs/.sounds/beepalert.wav') self.beepaccept = pygame.mixer.Sound('/home/user/MyDocs/.sounds/beepaccept.wav') self.beepupload= pygame.mixer.Sound('/home/user/MyDocs/.sounds/beepupload.wav') self.beepexpiry = pygame.mixer.Sound('/home/user/MyDocs/.sounds/beepexpiry.wav') def getImageList (self): """ do all the file magic to return a list of all the bitmaps """ self.renameBmp2Jpg () self.convertJpg2Bmp () self.convertGif2Bmp () self.setImageList () def renameBmp2Jpg (self): """Rename the extensions of the fake bmps""" bmpList = glob.glob (self.imagedirectory + '*.bmp') # find the fake BMP from bmpList, rename, and delete fake .bmp for bitmap in range (len (bmpList)): infile = bmpList[bitmap] if (Image.open(infile).format != 'BMP'): # change to == JPEG # RENAME f, e = os.path.splitext(infile) outfile = f + ".jpg" Image.open(infile).save(outfile) # REMOVE BADNESS os.remove (infile) # assured that my bitmaps are really bitmaps! def convertJpg2Bmp (self): """convert jpegs to bitmap format, which pygame can read""" jpgList = glob.glob (self.imagedirectory + '*.jpg') for jpg in range (len (jpgList)): infile = jpgList[jpg] f, e = os.path.splitext (infile) outfile = f + ".bmp" Image.open(infile).save(outfile) os.remove(jpgList[jpg]) def convertGif2Bmp (self): """convert gifs to bitmap format, which pygame can read""" gifList = glob.glob (self.imagedirectory + '*.gif') for gif in range (len (gifList)): infile = gifList[gif] f, e = os.path.splitext (infile) outfile = f + ".bmp" Image.open(infile).save(outfile) os.remove(gifList[gif]) def setImageList (self): """ get all BMP in directory, and they're all real bitmaps! """ self.fileList = glob.glob (self.imagedirectory + '*.bmp') for imageindex in range (len(self.fileList)): self.imageList.append(pygame.image.load(self.fileList[imageindex])) # self.imageList[imageindex] = pygame.image.load(self.fileList[imageindex]) for image in self.imageList: self.rectList.append (image.get_rect()) self.numFiles = len(self.imageList) def resizeImages (self): """ makes images fullscreen-size """ # RESIZES to FIT SCREEN for imageindex in range (len(self.imageList)): self.imageList[imageindex] = pygame.transform.scale(self.imageList[imageindex], self.size) self.initImages() def initImages (self): """ situate which image to display """ print 'in initImages' print 'imageIndex is ' + str(self.imageIndex) if len (self.imageList) > 0: # images are available self.currImage = self.imageList[self.imageIndex] self.currRect = self.rectList[self.imageIndex] else: print 'no images!' def listenEvents (self): """ listening for key stroke events """ for event in pygame.event.get(): if event.type == pygame.QUIT: os.remove(self.outRequest) sys.exit() pygame.event.pump() keyinput = pygame.key.get_pressed() if keyinput[K_ESCAPE] or keyinput[K_BACKSPACE] or keyinput[K_CLEAR] or pygame.event.peek(QUIT): if self.drawQuitPrompt() == True: os.remove(self.outRequest) sys.exit() if keyinput[K_LEFT]: if len (self.imageList) > 1: # multiple images available self.drawTransferIndicator (action = 'browse', state = 'prev') self.imageIndex = (self.imageIndex - 1) % len(self.imageList) print 'key left' if keyinput[K_RIGHT]: if len (self.imageList) > 1: # multiple images available self.drawTransferIndicator (action = 'browse', state = 'next') self.imageIndex = (self.imageIndex + 1) % len(self.imageList) print 'key right' """ DISABLE TRANSFERS """ if keyinput[K_UP]: # UPLOAD print 'key up' if self.numFiles > 0: # not empty self.uploadImage() else: self.drawMessage('sorry! there are no images in your stash...', 'try downloading some for a simple start...') if keyinput[K_DOWN]: # DOWNLOAD print 'key down' self.downloadImage() """ """ if keyinput[K_F4]: # open menu key to DELETE print 'delete button' if self.numFiles > 0: # not empyt self.deleteImage() else: self.drawMessage('sorry! there are no images in your stash...', 'try downloading some for a simple start...') if keyinput[K_RETURN]: # VIEW UPLOAD HISTORY print 'return button' self.drawHistory() print str(self.numFiles) + ' files' def listenFiles (self): """ listening for new images incoming, or images removed """ """ listening also to download requests by others """ requestList = glob.glob (self.imagedirectory + '*.request') # any requests for image? requestList.remove (self.outRequest) # hacky way of not counting oneself # SOMEONE'S REQUESTING IMAGE if len(requestList) > 0: self.uploadImage() for request in requestList: f = open (request, 'r') # READ PROFILE OF WHOSE REQUESTING requestprofile = pickle.load(f) requestprofile['image'] = pygame.transform.scale(self.currImage, (100,60)) requestprofile['time'] = str(time.asctime()) # if len (self.history) == self.historymax: # AT MAX CAP self.history.insert (0, requestprofile) os.remove(request) print 'upload history is ' + str(self.history) fileListTemp= glob.glob (self.imagedirectory + '*.bmp') # RESCOUR numFilesTemp = len (fileListTemp) if numFilesTemp > self.numFiles: # IMAGES ADDED newFiles = filter (lambda x: x not in self.fileList, fileListTemp) print 'newFiles are ' + str(newFiles) if self.numFiles == self.numFilesMax: # REACHED MAX CAPACITY self.drawMessage('you have reached max capacity!', 'to replenish images, files must either', string3 = 'be removed or be due to expire...') for newfile in newFiles: os.remove(newfile) return # GET OUT OF THE KITCHEN imageAccepted = False # need user to manually accept for index in range (len (newFiles)): print 'index = ' + str(index) print 'newFiles[index] = ' + str (newFiles[index]) # LOAD ONLY AFTER FILE IS DEEMED ACCESSIBLE while True: try: pygame.image.load(str(newFiles[index])) break except pygame.error: print 'not finished loading' """ stat = os.stat(str(newFiles[index])) size1 = stat.st_size time1 = stat.st_mtime print 'at time ' + str(time1) + ' size ' + str(size1) pygame.time.wait(100) stat = os.stat(str(newFiles[index])) size2 = stat.st_size time2 = stat.st_mtime print 'at time ' + str(time2) + ' size ' + str(size2) while size2 > size1: print 'in while loop' size1 = size2 time1 = time2 pygame.time.wait(800) stat = os.stat(str(newFiles[index])) size2 = stat.st_size time2 = stat.st_mtime print '1 at time ' + str(time1) + ' size ' + str(size1) print '2 at time ' + str(time2) + ' size ' + str(size2) """ # MAKING IMAGES WORK OUT newImage = pygame.image.load(str(newFiles[index])) newResizedImage = pygame.transform.scale(newImage, self.size) newImageEnhance = Image.open (str(newFiles[index])) newResizedImageEnhance = newImageEnhance.resize(self.size) """ curralpha = newResizedImage.get_alpha() print 'curralpha is ' + str(curralpha) if curralpha == None: newalpha = 200 else: newalpha = curralpha * 0.8 print 'newalpha is ' + str(newalpha) newResizedImage.set_alpha(newalpha) modifiedImage = newResizedImage print modifiedImage """ # newImageEnhance = Image.open(str(newFiles[index])) # newResizedImageEnhance = newImageEnhance.resize(self.size) """ ENHANCING IS REALLY SLOW """ """ enhancer = ImageEnhance.Contrast(newResizedImageEnhance) modifiedImage = enhancer.enhance(self.enhancefactor) """ """ OLD JAGGED DEGRADATION """ modifiedImage = pygame.transform.scale(newResizedImage, (self.width / 4, self.height / 4)) modifiedImage = pygame.transform.scale(modifiedImage, self.size) # NEW # (f, e) = os.path.splitext(newFiles[index]) modifiedImageFile = f + '.mod' + e # modifiedImage.save(modifiedImageFile) pygame.image.save (modifiedImage, modifiedImageFile) os.remove(newFiles[index]) if self.downloadFlag: # user intention to download print 'download? ' + str(self.downloadFlag) self.downloadFlag = False print 'download? ' + str(self.downloadFlag) imageAccepted = True else: # unsolicited incoming file # GET USER APPROVAL FOR ACCEPTING INCOMING FILE self.beepaccept.play() # AUDIO NOTIFY userWaitTime = 10 startTime = time.time() currTime = time.time() elapsedTime = currTime - startTime while elapsedTime < userWaitTime: print 'waiting for user input' keyinput = pygame.key.get_pressed() if keyinput[K_RETURN]: print 'return key accepted' imageAccepted = True # THE MONEY SHOT break self.drawAcceptFile(newImage) self.drawTimer(elapsedTime, userWaitTime) print 'drew icon' pygame.event.pump() currTime = time.time() elapsedTime = currTime - startTime if imageAccepted: self.drawTransferIndicator (action = 'download', state = 'start') self.fileList.append (modifiedImageFile) # os.remove (newFiles[index]) # self.fileList.append(newFiles[index]) print 'appended, new fileList: ' + str(self.fileList) self.imageList.append(modifiedImage) # degraded file self.rectList.append(newResizedImage.get_rect()) else: print 'image is not accepted, deleting file' # os.remove(str(newFiles[index])) os.remove (modifiedImageFile) print 'imageflag ' + str(imageAccepted) if imageAccepted: self.numFiles = numFilesTemp # RENEW IMAGE INVENTORY self.imageIndex = self.numFiles - 1 # INDEX OF RECENT IMAGE self.initImages() self.downloadFlag = False # hack? print 'completed newfile addition process' self.drawTransferIndicator (action = 'download', state = 'end') pygame.time.wait(1000) else: self.initImages() print 'image not accepted, no action' if numFilesTemp < self.numFiles: # IMAGES REMOVED oldFiles = filter (lambda x: x not in fileListTemp, self.fileList) for index in range (len (oldFiles)): print 'index is ' + str(index) print 'oldfiles[index] is ' + str(oldFiles[index]) print 'fileList is ' + str(self.fileList) indexremove = self.fileList.index(str(oldFiles[index])) print 'indexremove is ' + str(indexremove) print 'len of fileList ' + str(len(self.fileList)) self.fileList.pop(indexremove) self.imageList.pop(indexremove) self.rectList.pop(indexremove) print 'len of fileList now ' + str(len(self.fileList)) # change display if image has now disappeared if indexremove == self.imageIndex: self.imageIndex = self.imageIndex % numFilesTemp print 'indexremove is now ' + str(indexremove) self.numFiles = numFilesTemp # RENEW IMAGE INVENTORY print 'completed oldfile removal process' print 'new image index = ' + str(self.imageIndex) def maintainFiles (self): """ checks to see if any have expired, and then remove """ expiredFileIndices = [] for fileindex in range (len (self.fileList)): file = self.fileList[fileindex] filestat = os.stat(file) age = time.time() - filestat.st_mtime print 'age is ' + str(age) if age > self.expirytime: expiredFileIndices.append(fileindex) expiredFileIndices.sort() expiredFileIndices.reverse() print expiredFileIndices for fileindex in expiredFileIndices: self.beepexpiry.play() os.remove(self.fileList[fileindex]) self.fileList.pop(fileindex) self.imageList.pop(fileindex) self.rectList.pop(fileindex) self.numFiles = len (self.imageList) self.drawMessage ('an image is transpiring...', 'you now have ' + str(self.numFiles) + ' files on hand') if self.numFiles > 0: self.imageIndex = self.imageIndex % self.numFiles else: self.imageIndex = 0 self.initImages() """ file = self.fileList [self.imageIndex] # WANT TO DELETE? deleteFlag = self.drawDeletePrompt() if deleteFlag == True: print len(self.imageList) self.fileList.pop(self.imageIndex) self.imageList.pop(self.imageIndex) self.rectList.pop(self.imageIndex) self.numFiles = len(self.imageList) if self.numFiles > 0: self.imageIndex = self.imageIndex % self.numFiles else: self.imageIndex = 0 print len (self.imageList) self.initImages() os.remove(file) """ def uploadImage (self): """ transmits currently displayed image to other unit via scp """ self.beepupload.play() # SOUND ALERT if len(self.imageList) > 0: # there are images available # VISUAL FEEDBACK self.drawTransferIndicator (action = 'upload', state = 'start') indicateDelay = 1000 # how long icon is on screen filename = self.fileList [self.imageIndex] print filename command = 'scp ' + filename + ' ' + self.remoteuser + '@' + self.remotehost + ":" + self.remotedirectory print command os.system(command) print 'image uploaded' self.drawTransferIndicator (action = 'upload', state = 'end') pygame.time.wait(indicateDelay) else: # no images print 'there are no images to upload' def downloadImage(self): """ requests to download image from another unit """ # VISUAL FEEDBACK self.drawTransferIndicator (action = 'download', state = 'start') print 'in download image' requestcommand = 'scp ' + self.outRequest + ' ' + self.remoteuser + '@' + self.remotehost + ":" + self.remotedirectory os.system(requestcommand) print 'download request made' self.downloadFlag = True # user consciously wants an image def deleteImage(self): """deletes current image from the image directory, display""" print 'in delete image' file = self.fileList [self.imageIndex] # WANT TO DELETE? deleteFlag = self.drawDeletePrompt() if deleteFlag == True: print len(self.imageList) self.fileList.pop(self.imageIndex) self.imageList.pop(self.imageIndex) self.rectList.pop(self.imageIndex) self.numFiles = len(self.imageList) if self.numFiles > 0: self.imageIndex = self.imageIndex % self.numFiles else: self.imageIndex = 0 print len (self.imageList) self.initImages() os.remove(file) def drawDeletePrompt(self): font = pygame.font.Font(self.defaultfont, 60) fontsmall = pygame.font.Font(self.defaultfont, 60) while 1: pygame.event.pump() keyinput = pygame.key.get_pressed() pygame.draw.rect(self.screen, self.pink, Rect((0,0), (self.width, 100))) self.screen.blit(font.render('delete?', True, self.white), self.screen.get_rect().move(10,10)) pygame.display.flip() if keyinput[K_RETURN]: self.screen.blit(fontsmall.render('ok!', True, self.white, self.pink), self.screen.get_rect().move(240,10)) pygame.display.flip() pygame.time.wait(1000) return True if keyinput[K_UP] or keyinput[K_DOWN] or keyinput[K_LEFT] or keyinput[K_RIGHT] or keyinput[K_ESCAPE]: self.screen.blit(fontsmall.render('canceled', True, self.white, self.pink), self.screen.get_rect().move(240,10)) pygame.display.flip() pygame.time.wait(1000) return False def drawQuitPrompt (self): font = pygame.font.Font(self.defaultfont, 60) fontsmall = pygame.font.Font(self.defaultfont, 60) while 1: pygame.event.pump() keyinput = pygame.key.get_pressed() pygame.draw.rect(self.screen, self.pink, Rect((0,0), (self.width, 100))) self.screen.blit(font.render('quit?', True, self.white), self.screen.get_rect().move(10,10)) pygame.display.flip() if keyinput[K_RETURN]: self.screen.blit(fontsmall.render('ok!', True, self.white, self.pink), self.screen.get_rect().move(240,10)) pygame.display.flip() pygame.time.wait(1000) return True if keyinput[K_UP] or keyinput[K_DOWN] or keyinput[K_LEFT] or keyinput[K_RIGHT]: self.screen.blit(fontsmall.render('canceled', True, self.white, self.pink), self.screen.get_rect().move(240,10)) pygame.display.flip() pygame.time.wait(1000) return False def drawTransferIndicator (self, action = 'upload', state = 'start'): """ VISUAL UP ARROW FOR UPLOADING """ teal = (13, 214, 174) pink = (214, 13, 174) white = (255,255,255) radiusBig = 50 radiusSmall = radiusBig / 2 centerx = self.width / 2 centery = self.height / 2 center = (centerx, centery) if action == 'upload': if state == 'start': triangleCoords = ((350 ,175), (450 ,175), (400,100)) stemCoords = ((390, 175), (390, 230), (410, 230), (410, 175)) pygame.draw.circle(self.screen, teal, center, radiusBig) pygame.draw.polygon(self.screen, white, triangleCoords) pygame.draw.polygon(self.screen, white, stemCoords) if state == 'end': pygame.draw.circle (self.screen, white, (400, 50), radiusSmall) if action == 'download': if state == 'start': triangleCoords = ((350, 305), (450, 305), (400, 380)) stemCoords = ((390, 250), (390, 305), (410, 305), (410, 250)) pygame.draw.circle (self.screen, pink, center, radiusBig) pygame.draw.polygon(self.screen, white, triangleCoords) pygame.draw.polygon(self.screen, white, stemCoords) if state == 'end': pygame.draw.circle(self.screen, white, (400, 430), radiusSmall) if action == 'browse': if state == 'next': stemCoords = ((750, 230), (750, 250), (695, 250), (695, 230)) pygame.draw.polygon(self.screen, white, stemCoords) triangleCoords = ((750, 220), (750, 260), (790, 240)) pygame.draw.polygon(self.screen, white, triangleCoords) if state == 'prev': stemCoords = ((50, 230), (50, 250), (105, 250), (105, 230)) pygame.draw.polygon(self.screen, white, stemCoords) triangleCoords = ((50, 220), (50, 260), (10, 240)) pygame.draw.polygon(self.screen, white, triangleCoords) pygame.display.flip() def drawEmptyScreen (self): """ graphical indication there are no images available to show """ self.screen.fill (self.teal) # all empty... pygame.draw.rect (self.screen, self.white, Rect((750,430 ), (25,25)), 10) pygame.display.flip() def drawMessage (self, string1, string2, string3 = ''): """ let user know something by writing text to screen""" self.beepalert.play() # sound beep font = pygame.font.Font(self.defaultfont, 30) self.screen.blit(font.render(string1, True, self.white), self.screen.get_rect().move(10,10)) self.screen.blit(font.render(string2, True, self.white), self.screen.get_rect().move(30,50)) self.screen.blit(font.render(string3, True, self.white), self.screen.get_rect().move(30,90)) pygame.display.update() pygame.time.wait(3000) def drawHistory (self): """ prints history of activity - first, requests""" self.screen.fill(self.pink) font = pygame.font.Font(self.defaultfont, 20) bigfont = pygame.font.Font(self.defaultfont, 40) self.screen.blit(bigfont.render('most recent activity', True, self.white), self.screen.get_rect().move(360, 10)) x = 50 y = 100 for profile in self.history: for k, v in profile.iteritems(): if type(v) == type (''): self.screen.blit(font.render (str(v), True, self.white), self.screen.get_rect().move (x, y)) else: self.screen.blit (v, self.screen.get_rect().move(x,y)) x = x + 150 x = 50 y = y + 75 while True: pygame.display.update() pygame.event.pump() keyinput = pygame.key.get_pressed() if keyinput [K_UP] or keyinput [K_DOWN] or keyinput [K_LEFT] or keyinput [K_RIGHT]: break def drawAcceptFile (self, image): # also pass in filename """ implores user to accept incoming image within some defined time threshold """ white = (255,255,255) thumbnailSize = (100,60) thumbnail = pygame.transform.scale(image, thumbnailSize) stemCoords = ((25, 10), (40,10), (40, 45), (25, 45)) # width 15 triangleCoords = ((10, 45), (55, 45), (32, 70)) pygame.draw.polygon (self.screen, white, stemCoords) pygame.draw.polygon (self.screen, white, triangleCoords) # downarrow self.screen.blit(thumbnail, Rect ((65, 10), thumbnailSize)) # thumbnail preview # questionmark strokewidth = 10 pygame.draw.line(self.screen, white, (175, 10), (220, 10), strokewidth) pygame.draw.line(self.screen, white, (220, 10), (220, 30), strokewidth) pygame.draw.line(self.screen, white, (220,30), (197, 30), strokewidth) pygame.draw.line(self.screen, white, (197,30), (197, 45), strokewidth) pygame.draw.line(self.screen, white, (197, 70), (197, 70 - strokewidth), strokewidth) pygame.display.flip() def drawTimer (self, elapsedTime, userWaitTime): white = (255,255,255) teal = (13, 214, 174) pink = (214, 13, 174) timerRect = Rect((65, 80), (100,100)) # timerBackground = Rect ((230, 10), (80, 80)) start_angle = 0 stop_angle = (elapsedTime / userWaitTime) * 2 * math.pi width = 10 # pygame.draw.rect(self.screen, pink, timerBackground ) pygame.draw.arc(self.screen, white, timerRect, start_angle, stop_angle, width) pygame.display.flip() def showDisplay (self): """ outputs selected image onto screen """ if len (self.imageList) > 0: # there are images available self.currRect.inflate_ip (self.width - self.currRect.width, self.height - self.currRect.height) self.currRect.center = (self.width / 2, self.height / 2 ) self.screen.fill(self.backgroundcolor) self.screen.blit (self.currImage, self.currRect) else: # image directory is empty print 'no images to display' self.drawEmptyScreen() if self.downloadFlag: # in process of downloading self.drawTransferIndicator (action = 'download', state = 'start') pygame.display.flip() def execute(self): """ display and listen """ while 1: # print pygame.time.get_ticks() self.listenEvents () self.listenFiles () self.maintainFiles () self.showDisplay () self.initImages() if __name__ == '__main__': if len (sys.argv) != 5: print 'oopsie! usage: urban.py [hostname] [remoteuser] [remotehost] [remotedirectory]' sys.exit() # urban = Urban(remoteuser = 'cml', remotehost = '18.85.18.121', remotedirectory = '/Users/cml/Documents/smg/maemo/maemae/MyDocs/.images') urban = Urban(name = str(sys.argv[1]), outRequest = '/media/mmc1/' + str(sys.argv[1]) + '.request', remoteuser = str(sys.argv[2]), remotehost = str(sys.argv[3]), remotedirectory = str(sys.argv[4])) print 'object initialised' urban.getImageList() print 'got image list' urban.resizeImages() print 'images initialised and resized' print 'ready to execute' urban.execute()