''' 2021-06-07 I haven't run in years. I never really liked The PIL Library, as I always got an error message on import. These days, I'd most definitely use: numpy, skimage, or the like, instead # # # Created on Apr 1, 2014 @author: Brett Paufler Copyright Brett Paufler USES PIL IMAGES KILLED MAKE DIRECTORY JUST NOT GOING TO USE overlay/watermark = useful tool pil_filter_effects (mega explosion, sampler) USES PIL ''' #TODO: requires ./temp directory #import PIL from PIL import Image, ImageFilter import numpy import os #import itertools from itertools import compress, permutations #Imports gif maker script scriptPath = './gif/' os.sys.path.append(os.path.abspath(scriptPath)) import gif as gif DIR_IN = '.\\input\\' DIR_OUT = '.\\output\\' #IMAGE_LIST = [DIR_IN + image for image in os.listdir(DIR_IN)] # returns a list of pictures (files with noted file types) def get_image_list(dir_in="./input/"): image_list = [os.path.abspath(dir_in + item) for item in os.listdir(dir_in)] return image_list # end get_image_list() ### Watermark Utilities def watermark(*args, **kwargs): '''Alias for overlay, which uses PIL Image objects (img)''' return overlay(*args, **kwargs) def overlay(img_base, img_overlay, location='lower_left', offset=10, lower_left=True, lower_right=False, upper_left=False, upper_right=False, center=False): '''Overlays img_overlay on top of img_base, wherever img_overlay exists, it overides img_base. Intended use is as a watermark applicator img_base: PIL image img_overlay: PIL image must be smaller than img_base offset: distance from edge in pixels, has no meaning for center locations: lower_left, lower_right, upper_left, upper_right, center For any value True, adds overlay to appropriate location returns a PIL image nothing is saved ''' img_base = img_base.convert("RGBA") img_overlay = img_overlay.convert("RGBA") ib_w, ib_h = img_base.size io_w, io_h = img_overlay.size #not tested corners = [ (offset, ib_h - io_h - offset), #'lower_left': (ib_w - io_w - offset, ib_h - io_h - offset), #'lower_right': (offset, offset), #'upper_left': (ib_w - io_w - offset, offset), #'upper_right': (ib_w/2 - io_w/2, ib_h/2 - io_h/2 ), #'center': ] corner_selectors = [lower_left, lower_right, upper_left, upper_right, center] corners = list(compress(corners, corner_selectors)) for corner in corners: img_base = img_base.paste(img_overlay, corner, img_overlay) print img_base return img_base #TODO: update watermark location def watermark_inplace(image_in, image_overlay='./watermarks/water.png', **kwargs): '''Adds watermark (or other overlay) in place to an image. image_in: path to input image watermark: path to watermark **kwargs: locations tags: upper_left, lower_right, center offset: how far from true location''' img_base = Image.open(image_in) img_water = Image.open(image_overlay) img_out = watermark(img_base, img_water, **kwargs) img_out.save('./output/water_test.png') ### Stock Filter Effects def pil_filter_effects(): '''Tester function exploring PIL base ImageFilter. As with all testers, most output is crap''' image_list = get_image_list() print image_list for image_in in image_list: img = Image.open(image_in) print img print image_in image_out = image_in.replace('\\input\\', '\\output\\') print image_out pil_effects = { 'FIND_EDGES': ImageFilter.FIND_EDGES, 'COUNTOUR': ImageFilter.CONTOUR, 'BLUR': ImageFilter.BLUR, 'DETAIL': ImageFilter.DETAIL, 'EDGE_ENHANCE': ImageFilter.EDGE_ENHANCE, 'EDGE_ENHANCE_MORE': ImageFilter.EDGE_ENHANCE_MORE, 'EMBOSS': ImageFilter.EMBOSS, 'SMOOTH': ImageFilter.SMOOTH, 'SMOOTH_MORE': ImageFilter.SMOOTH_MORE, 'SHARPEN': ImageFilter.SHARPEN, 'GuassianBlur': ImageFilter.GaussianBlur, 'MaxFilter': ImageFilter.MaxFilter, 'MedianFilter': ImageFilter.MedianFilter, 'MinFilter': ImageFilter.MinFilter, 'ModeFilter': ImageFilter.ModeFilter, } for label, pil_effect in pil_effects.items(): save_name = image_out[:-4] + '_' + label + image_out[-4:] print save_name img_out = img.kernel(pil_effect) img_out.save(save_name) #TODO: THIS IS WHERE STOPPING ON THIS FILE def to_here(): pass def compoundEdgeEffects(pp, n=4, onlyLast=True, save=True): ''' #n = number of iterations ''' print "compoundEdgeEffects() called" p = pp['i'] print pp['i'] picName = pp['n'] print pp['n'] pathName = './temp/' + picName # loop that applies the effect for x in range(1, n + 1 , 1): pN = pathName + 'FE' + str(x) + 'FIND_EDGES.jpg' print pN #this is the effect, applied p = p.kernel(ImageFilter.FIND_EDGES) #optional saves, onlyLast if not onlyLast: if save: p.save(pN) #or saves only once outside the loop if x == n: if onlyLast: print "compoundEdgeEffect saved " + pN if save: p.save(pN) p = p.convert('RGBA') return p print "compoundEdgeEffects() ended" # compoundEdgeEffects() ended #compoundEdgeEffects() #simply full layer swap of r, g, b values #split merge exercise def allColorSwap(): print "allColorSwap() called" #makeOutputDirectory('filterEffects') picList = get_image_list() print "palerShadeOfGrass() ended" #the Guts of the function for pic in picList: print "Working on " + pic p = Image.open(pic) picName = pic[:-4] pathName = './temp/' + picName p = p.convert('RGBA') r, g, b = {}, {}, {} r["c"], g["c"],b["c"], a = p.split() r["n"], g["n"], b["n"] = "R", "G", "B" colors = [r,g,b] layers = [] for c in permutations(colors): label = c[0]["n"] + c[1]["n"] +c [2]["n"] z = Image.merge("RGBA", [c[0]["c"], c[1]["c"],c[2]["c"],a] ) pN = pathName + label + 'ShadeGREEN.jpg' print pN z.save(pN) layers.append(z) ''' #Code for turning to Gif - doesn't look good pN = pN[:-4] + "_GIF.gif" convertToGif(layers, pN, 0.1) print "Working on Second Gif" pN = pN[:-4] + "_GIF2.gif" gif.writeGif(pN, layers, 0.1) ''' print "allColorSwap() ENDED" # end all Color Swap #keeps numbered labels in order def numForLabel(n): label = '%0.3d' % n return label #if n < 10: # t = "00" + str(n) #elif n < 100: # t = "0" + str(n) #else: # t = str(n) #return t def fadeSingleLayer(img, factor=10): print "fadeSingleLayer Called" tA = numpy.asarray(img) if factor != 0: tA = tA / factor elif factor == 0: tA = tA * 0 elif factor == 255: tA = tA * 255 print tA print tA.shape return Image.fromarray(tA) def fadeAllPictures(): print "fadeAllPictures called called" #makeOutputDirectory('filterEffects') picList = get_image_list() for pic in picList: picName = pic[:-4] pathName = './temp/' + picName img = Image.open(pic) img = img.convert('RGBA') r,g,b,a = img.split() for n in [0, 2, 5, 10, 25, 50, 100, 255]: rF = fadeSingleLayer(r,n) bF = fadeSingleLayer(b,n) z = Image.merge("RGBA", [rF,g,bF,a]) saveName = pathName + "fade" + numForLabel(n) + ".jpg" z.save(saveName) print "fadeAllPictures Ran to Completion" #end faceAllPictures #fadeAllPictures() #Returns an Iterable with all the pictures in a directory def allPicsInDir(dir_in="."): print "allPicsInDir Called" picList = get_image_list(dir_in) px = {} for pic in picList: px["n"] = pic[:-4] px["i"] = Image.open(pic) px["i"] = px["i"].convert('RGBA') yield px #end allPicsIndir #gives incremental Grett static effect #STILL WORKIGN ON def greenCircuitEffect(delay=0.20,gifOnly=True): ''' takes all pictures from base gallery and converts them into GIF with green special effects''' for x in allPicsInDir(): layers = [] x['n'] += "000" for num in [1, 2, 3, 4, 3, 2]: #range (1,5,1): x['n'] = x['n'][:-3] x['n'] += numForLabel(num) print x['n'] print num #y = 6 edgePic = compoundEdgeEffects(x, num, True, False) print edgePic r, g, _, _ = edgePic.split() zA = numpy.asarray(r) * 0 z = Image.fromarray(zA) z = Image.merge("RGBA", [z,g,z,g]) saveName = './temp/' + x['n'] + '.png' z = z.convert('P') if not gifOnly: z.save(saveName) layers.append(z) saveName = './temp/' + x['n'] + '_greenCircuitGIF' + '.gif' print layers print "GIF Making GIF" + saveName gif.writeGif(saveName, layers, delay) print "greenCircuitEffect ENDING" #END greenCircuitEffect #greenCircuitEffect(delay=0.125,gifOnly=False) def convertToGif(a=".", name="01-convertToGif.gif", speed=0.5): ''' a can be a single Picture or a can be a list of PIL images converts directory or list of images to animated gif must be same size, no provision for size checking or cropping ''' print "convertToGif CALLED" pics = [] if isinstance(a, str): dPL = get_image_list(a) for item in dPL: pics.append(Image.open(a + "/" + item)) elif isinstance(a, list): for z in a: z.convert('P') pics.append(z) print "Making the Gif..." gif.writeGif(name, pics, speed) print "convertToGif MADE" #convertToGif Ends #trial Run Hangs, so perhaps output as gif to a directory first #But that's for another day #convertToGif(".//gifStock") def testSquares(): '''Outputs a few test images and prints the numpy Matrixes to view and learn''' size = (15,10) RGBAwhite = Image.new("RGBA", size, "white") RGBAwhite.save("./temp/RGBAwhite.png", "png") RGBAblack = Image.new("RGBA", size, "black") RGBAblack.save("./temp/RGBAblack.png", "png") _, _, _,a = RGBAwhite.split() wA = numpy.asarray(RGBAwhite) bA = numpy.asarray(RGBAblack) aA = numpy.asarray(a) numpy.save("./temp/RGBAwhite.npy", wA) numpy.save("./temp/RGBAblack.npy", bA) numpy.savetxt("./temp/RGBAalphaOnly.txt", aA, fmt='%i' ) print wA print wA.shape print "NEXT NEXT NEXT" print aA print aA.shape #end testSquares( #testSquares() def defaultLabel(bname, n=0, ext="png", dL="./temp"): '''returns a preformatted label, bname = textString (typical source + effect, n= number in series''' if not dL == "": if not dL.endswith("/"): dL += "/" dL += bname dL += numForLabel(n) dL += "." + ext return dL def greenPNG(pic): '''takes a png or like and returns a green picture object''' print "greenPNG called, returning a green Picture" pic = pic.convert('RGBA') r,g,_, _ = pic.split() zA = numpy.asarray(r) * 0 z = Image.fromarray(zA) z = Image.merge("RGBA", [z,g,z,g]) return z def cannyGif(): ''' takes all pics in base directory and returns a cannyFilter Gif, per above function Taks no arguements, returns a picture ''' picList = allPicsInDir() for pic in picList: test = cannyFilter(pic, False) print "Lenght of Test, Short, Final" print len(test) print test short = test[-2:0:-1] print len(short) final = test + short #numpy.concatenate([test,short]) print len(final) for item in final: print item name = "./temp/" + pic['n'] + "_cannyFilter_GIF.gif" gif.writeGif(name, final, 0.15, subRectangles=False, dither=True, dispose=2) ''' #def writeGif(filename, images, duration=0.1, repeat=True, dither=False, #nq=0, subRectangles=True, dispose=None) ''' def cannyFilter(img, saveEach=True, green=True, highLowRange=[10], sigmaValueRange=[0.10, 0.25, 0.50, 1.0, 2.0, 4, 10, 15, 20, 22.5]): ''' img can be a single image or group of images from allPicsInDir applies all variations of the the canny kernel from skimage to selected image outputting the results as a SAVED IMAGE IN the filterEffects file Pictures tend to look better in reverse order as an animation highLowRange can be any list, I found no difference for different values sigmaValueRange is where all the action is, lower Number is more picture like, at 25 reduces to PURE BLACK in most instances appended to return an array of all the images Returned array is of PIL images ''' print "cannyFilter called" if isinstance(img,str): bN = img[:-4] pic = Image.open(img) pic = pic.convert('L') else: pic = img["i"].convert("L") bN = img['n'] returnArray = [] #I didn't find much difference changing the high low value for highLow in highLowRange: #numpy.arange(5, 26, 5): hLN = bN + "Canny-hL" + numForLabel(highLow) #ALL 'N' hlN, bN refer to Naming output string #highly subjective magic numbers, pictures run better in reverse for s in sigmaValueRange: #numpy.arange(.25, 2.6, 0.25): oN = hLN + "sig" cE = filter.canny(numpy.asarray(pic), sigma=s, low_threshold=highLow, high_threshold=(highLow * 2)) cE = cE.astype(int) cE = cE * 255 #print cE.shape outPic = Image.fromarray(cE,"L") if green: outPic = greenPNG(outPic) label = defaultLabel(oN, s) if saveEach == True: outPic.save(label, "png") returnArray.append(outPic) print "cannyFilter ending RETURNING A PIL IMAGE OBJECT" print returnArray return returnArray #At this Point, returnArray not actually checked #end cannyFilter if __name__ == '__main__': print 'pil_filter_effects running as main' #pil_filter_effects() watermark_inplace() #watermark_four_corners(img_base, img_overlay, offset, center) print "PIL ended" four_dict = { 'upper_left': True, 'lower_left': True, 'upper_right': True, 'lower_right': True, 'center': True, 'offset': 100}