Working with ranges in pictures Barb Ericson Georgia Institute of Technology Oct 2010 02-RangesInPictures 1 Learning Goals • How do you create a range of values? • What is a two-dimensional array? • How do you loop through a two-dimensional array? – Nested loops • How do you simplify a hard problem? • How do you copy one picture to another? • How do you make a general function? 02-RangesInPictures 2 Try the following in JES >>> print range (0, 3) >>> print range (5, 7) >>> print range (0,10) >>> print range (3,1) What do you think the range function does? Creating ranges of values You can create a range of values in python >>> print range (0,3) [0, 1, 2] [0,1,2] is an array of values >>> print range (0 ,10) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> print range (3,1) [] [] is an array with no values Pictures are really two dimensional • Pictures have a width and a height – getWidth(picture) – getHeight(picture) • You can access a pixel of a picture by using the x and y values for the pixel – pixel = getPixel(picture, x, y) Working with part of a picture • What if you want to only modify part of a picture? – Not every pixel in the picture • You need to be able to say where you want to start and stop – Using ranges for x in range(0, getWidth(picture)): for y in range(0, getHeight(picture) / 2): pixel=getPixel(picture, x, y) Challenge • Create a version of decrease red that only changes the red in the top half of the picture Mirroring a Picture • If you put a vertical mirror in the middle of a picture and looked in the mirror you would see something strange Mirroring from left to right What is the Vertical Mirror for this? • Try the solve the problem for small samples • If you can’t solve it on a small sample – You can’t write a program to solve it 0 1 2 0 1 2 3 1 4 5 6 2 7 8 9 0 0 1 2 1 2 Mirror Vertical Algorithm • Loop through all the rows (y starts at 0 and is less than the picture height) – Loop with x starting at 0 and x less than the midpoint (mirror point) value • Get the left pixel at x and y • Get the right pixel at width – 1 -x • Set the color for the right pixel to be the color of the left pixel 1 2 3 4 5 5 4 3 2 1 1 2 3 4 5 1 2 3 2 1 5 4 3 4 5 1 2 3 2 1 Algorithm to Code def mirrorVertical(source ): mirrorPoint = getWidth(source) / 2 width = getWidth(source) for y in range(0, getHeight(source )): for x in range(0, mirrorPoint ): leftPixel = getPixel(source, x, y) rightPixel = getPixel(source, width - x - 1,y) color = getColor(leftPixel) setColor(rightPixel ,color) Challenge – right to left? • Copy mirrorVertical and modify it to mirror from right to left instead – What part of the function needs to change? 1 2 3 4 5 5 4 3 2 1 1 2 3 4 5 5 4 3 4 5 1 2 3 2 1 4 5 3 4 5 Mirror Horizontal • What about mirroring around a mirror held horizontally in the vertical center of the picture? – Like a reflection in a lake? Thinking Through Mirror Horizontal • Again think of a number at each x and y location – Instead of a color – And try it with a small sample • How can we write a nested for loop to do this? 0 1 2 0 1 2 3 1 4 5 6 2 7 8 9 0 1 2 0 1 2 3 1 4 5 6 2 1 2 3 What is the horizontal mirror of this? 0 • Try to solve the problem for several small samples problems • See if you can come up with the algorithm to solve it – Test it more small samples 0 1 2 1 2 3 4 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Mirror Horizontal Algorithm • Get the height midpoint – Picture height / 2 • Loop through all the x values – Loop from y=0 to y < vertical midpoint • Get the top pixel – At x and y • Get the bottom pixel 1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 1 2 3 – Height - 1 - y • Set the bottom pixel’s color to the top pixel color Challenge • Write the function to mirror top to bottom • Write the function to mirror from bottom to top • How about diagonal mirroring? – In just a square section Mirror part of a picture • Can we mirror just part of a picture? Mirror part of the temple def mirrorTemple (): source = makePicture(getMediaPath("temple.jpg")) mirrorPoint = 277 for x in range (14, mirrorPoint ): for y in range (28 ,98): print "Copying color from",x,y,"to",mirrorPoint+mirrorPoint -1-x,y pleft = getPixel(source,x,y) pright = getPixel(source ,mirrorPoint+mirrorPoint -1-x,y) setColor(pright ,getColor(pleft )) show(source) return source fixedTemple = mirrorTemple() Copying Pixels to a New Picture • Need to track the source picture x and y – And the target picture x and y 1 2 3 4 • We can use a blank picture – As the target picture • Several blank pictures are available – 640x480.jpg – 7inX95in.jpg 1 2 3 4 Copy Picture Algorithm • Copy a picture to the 7 by 9.5 inch blank picture – Create the target picture object – Invoke the method on the target picture • Create the source picture object • Loop through the source picture pixels – Get the source and target pixels – Set the color of the target pixel to the color of the source pixel Copying pixels • In general, what we want to do is to keep track of a sourceX and sourceY, and a targetX and targetY. – We increment (add to them) in pairs • sourceX and targetX get incremented together • sourceY and targetY get incremented together – The tricky parts are: • Setting values inside the body of loops • Incrementing at the bottom of loops Copy picture code def copyBarb (): # Set up the source and target pictures barbf=getMediaPath("barbara.jpg") barb = makePicture(barbf) canvasf = getMediaPath("7inX95in.jpg") canvas = makePicture(canvasf) # Now , do the actual copying targetX = 0 for sourceX in range(0, getWidth(barb )): targetY = 0 for sourceY in range(0, getHeight(barb )): color = getColor(getPixel(barb ,sourceX ,sourceY )) setColor(getPixel(canvas ,targetX ,targetY), color) targetY = targetY + 1 targetX = targetX + 1 show(barb) show(canvas) return canvas Challenge • How do we change where we copy the picture to? – Can we start the copy somewhere other than 0,0? Create a Collage Collage Code def createCollage (): flower1=makePicture(getMediaPath("flower1.jpg")) flower2=makePicture(getMediaPath("flower2.jpg")) canvas=makePicture(getMediaPath("640 x480.jpg")) #First picture , at left edge targetX =0 for sourceX in range(0, getWidth(flower1 )): targetY=getHeight(canvas)-getHeight(flower1 )-5 for sourceY in range(0, getHeight(flower1 )): px=getPixel(flower1 ,sourceX ,sourceY) cx=getPixel(canvas ,targetX ,targetY) setColor(cx ,getColor(px)) targetY=targetY + 1 targetX=targetX + 1 Collage Code - continued #Second picture , 100 pixels over targetX =100 for sourceX in range(0, getWidth(flower2 )): targetY=getHeight(canvas)-getHeight(flower2 )-5 for sourceY in range(0, getHeight(flower2 )): px=getPixel(flower2 ,sourceX ,sourceY) cx=getPixel(canvas ,targetX ,targetY) setColor(cx ,getColor(px)) targetY=targetY + 1 targetX=targetX + 1 Collage Code - continued #Third picture , flower1 negated negative(flower1) targetX =200 for sourceX in range(0, getWidth(flower1 )): targetY=getHeight(canvas)-getHeight(flower1 )-5 for sourceY in range(0, getHeight(flower1 )): px=getPixel(flower1 ,sourceX ,sourceY) cx=getPixel(canvas ,targetX ,targetY) setColor(cx ,getColor(px)) targetY=targetY + 1 targetX=targetX + 1 Collage Code - continued #Fourth picture , flower2 with no blue clearBlue(flower2) targetX =300 for sourceX in range(0, getWidth(flower2 )): targetY=getHeight(canvas)-getHeight(flower2 )-5 for sourceY in range(0, getHeight(flower2 )): px=getPixel(flower2 ,sourceX ,sourceY) cx=getPixel(canvas ,targetX ,targetY) setColor(cx ,getColor(px)) targetY=targetY + 1 targetX=targetX + 1 Collage code - continued #Fifth picture , flower1 , negated with decreased red decreaseRed(flower1) targetX =400 for sourceX in range(0, getWidth(flower1 )): targetY=getHeight(canvas)-getHeight(flower1 )-5 for sourceY in range(0, getHeight(flower1 )): px=getPixel(flower1 ,sourceX ,source cx=getPixel(canvas ,targetX ,target) setColor(cx ,getColor(px)) targetY=targetY + 1 targetX=targetX + 1 show(canvas) return(canvas) General Copy Function def copy(source , target , targX , targY ): targetX = targX for sourceX in range(0, getWidth(source )): targetY = targY for sourceY in range(0, getHeight(source )): px=getPixel(source ,sourceX ,sourceY) tx=getPixel(target ,targetX ,targetY) setColor(tx ,getColor(px)) targetY=targetY + 1 targetX=targetX + 1 Better Collage Function def createCollage2 (): flower1=makePicture(getMediaPath("flower1.jpg")) flower2=makePicture(getMediaPath("flower2.jpg")) canvas=makePicture(getMediaPath("640 x480.jpg")) h1 = getHeight(flower1) h2 = getHeight(flower2) hc = getHeight(canvas) #First picture , at left edge copy(flower1 ,canvas ,0, hc - h1 – 5) #Second picture , 100 pixels over copy(flower2 ,canvas ,100 , hc – h2 – 5) Better Collage - continued #Third picture , flower1 negated negative(flower1) copy(flower1 ,canvas ,200 , hc – h1 – 5) #Fourth picture , flower2 with no blue clearBlue(flower2) copy(flower2 ,canvas ,300 , hc – h2 – 5) #Fifth picture , flower1 , negated with decreased red decreaseRed(flower1) copy(flower1 ,canvas ,400 , hc – h1 – 5) return canvas Challenge • Create your own collage – Use at least 1 picture – Use at least 3 image filters – Mirror the results Summary • You can create ranges of values – range(10) = 0 – 9 – range(0,10) • You can loop through a picture – Using x and y ranges • You can loop through part of a picture – By starting and ending at different values than normal • You can break long methods into shorter parts – Pull out common code and put it in a method