65
Copying: How it works Here's the initial setup:

Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

Embed Size (px)

Citation preview

Page 1: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

Copying: How it worksHere's the initial

setup:

Page 2: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

Copying: How it works 2After incrementing

the sourceY and targetY once (whether in the for or via expression):

Page 3: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

Copying: How it works 3After yet another

increment of sourceY and targetY:

When we finish that column, we increment sourceX and targetX, and start on the next column.

Page 4: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

Copying: How it looks at the endEventually, we copy

every pixel

Page 5: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

Making a collageCould we do

something to the pictures we copy in? Sure! Could either apply

one of those functions before copying, or do something to the pixels during the copy.

Could we copy more than one picture! Of course! Make a collage!

Page 6: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

def createCollage(): flower1=makePicture(getMediaPath("flower1.jpg")) print flower1 flower2=makePicture(getMediaPath("flower2.jpg")) print flower2 canvas=makePicture(getMediaPath("640x480.jpg")) print canvas #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 #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

#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 #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 #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,sourceY) cx=getPixel(canvas,targetX,targetY) setColor(cx,getColor(px)) targetY=targetY + 1 targetX=targetX + 1 show(canvas) return(canvas)

Page 170-171 (4ed edition)

Page 7: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

Can we make that easier?The collage code is

long, yet simple.It's the same thing

over-and-over.We can generalize

that copying loop, and with parameters, use it in many places.

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

Page 8: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

Exact same collage!def createCollage2():

flower1=makePicture(getMediaPath("flower1.jpg"))

print flower1

flower2=makePicture(getMediaPath("flower2.jpg"))

print flower2

canvas=makePicture(getMediaPath("640x480.jpg"))

print canvas #First picture, at left edge

copy(flower1,canvas,0,getHeight(canvas)-getHeight(flower1)-5)

#Second picture, 100 pixels over

copy(flower2,canvas,100,getHeight(canvas)-getHeight(flower2)-5)

#Third picture, flower1 negated negative(flower1)

copy(flower1,canvas,200,getHeight(canvas)-getHeight(flower1)-5)

#Fourth picture, flower2 with no blue clearBlue(flower2)

copy(flower2,canvas,300,getHeight(canvas)-getHeight(flower2)-5)

#Fifth picture, flower1, negated with decreased red

decreaseRed(flower1)

copy(flower1,canvas,400,getHeight(canvas)-getHeight(flower2)-5)

return canvas

Page 9: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):
Page 10: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

Bigger or Smaller?

Does this function make the src bigger or smaller on the canvas?

1.Increases size by 50%

2.Decreases size by 50%

3.Decreases size by 50% and skips some pixels in target

4.Increases size by 50% and skips some pixels in target

Page 11: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

>>> c = makePicture("caterpillar.jpg")>>> copyPicDifferent(c,c1,10,10)>>> explore(c1)>>> copyAnyPic(c,c1,10,10)>>> explore(c1)

Page 12: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

Transformation = Small changes in copyingMaking relatively small changes in this basic

copying program can make a variety of transformations.Change the targetX and targetY, and you copy

wherever you wantCropping: Change the sourceX and sourceY

range, and you copy only part of the program.Rotating: Swap targetX and targetY, and you

end up copying sidewaysScaling: Change the increment on sourceX

and sourceY, and you either grow or shrink the image.

Page 13: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

Copying face to small canvasdef copyHorseFaceSmall(): # Set up the source and target pictures src = makePicture("horse.jpg") canvas = makeEmptyPicture(163,308) # Now, do the actual copying targetX = 0 for sourceX in range(104,267): targetY = 0 for sourceY in range(114,422): color = getColor(getPixel(src,sourceX,sourceY)) setColor(getPixel(canvas,targetX,targetY), color) targetY = targetY + 1 targetX = targetX + 1 show(canvas) return canvas

Page 14: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

Changing while copyingdef copyHorseFaceSmallBlack(): hcol = makeColor(216,169,143) # Set up the source and target pictures src = makePicture("horse.jpg") canvas = makeEmptyPicture(163,308) # Now, do the actual copying targetX = 0 for sourceX in range(104,267): targetY = 0 for sourceY in range(114,422): color = getColor(getPixel(src,sourceX,sourceY)) if distance(color,hcol) < 40: setColor(getPixel(canvas,targetX,targetY), black) else: setColor(getPixel(canvas,targetX,targetY), color) targetY = targetY + 1 targetX = targetX + 1 show(canvas) return canvas

Page 15: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

Copying vs. Referencing>>> a = 100>>> b = a>>> print a,b100 100>>> b = 200>>> print a,b100 200>>> a = 300>>> print a,b300 200

Page 16: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

Referencing works differently>>> pictureBarb = makePicture("barbara.jpg")>>> pixel1 = getPixelAt(pictureBarb,0,0)>>> print pixel1Pixel red=168 green=131 blue=105>>> anotherpixel = pixel1>>> print anotherpixelPixel red=168 green=131 blue=105>>> setColor(pixel1,black)>>> print pixel1Pixel red=0 green=0 blue=0>>> print anotherpixelPixel red=0 green=0 blue=0

Page 17: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

Making a collageCould we do

something to the pictures we copy in? Sure! Could either apply

one of those functions before copying, or do something to the pixels during the copy.

Could we copy more than one picture! Of course! Make a collage!

Page 18: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

def createCollage(): flower1=makePicture(getMediaPath("flower1.jpg")) print flower1 flower2=makePicture(getMediaPath("flower2.jpg")) print flower2 canvas=makePicture(getMediaPath("640x480.jpg")) print canvas #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 #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

#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 #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 #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,sourceY) cx=getPixel(canvas,targetX,targetY) setColor(cx,getColor(px)) targetY=targetY + 1 targetX=targetX + 1 show(canvas) return(canvas)

Page 91-92 (2ed edition)

Page 19: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

Can we make that easier?The collage code is

long, yet simple.It's the same thing

over-and-over.We can generalize

that copying loop, and with parameters, use it in many places.

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

Page 20: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

Exact same collage!def createCollage2():

flower1=makePicture(getMediaPath("flower1.jpg"))

print flower1

flower2=makePicture(getMediaPath("flower2.jpg"))

print flower2

canvas=makePicture(getMediaPath("640x480.jpg"))

print canvas #First picture, at left edge

copy(flower1,canvas,0,getHeight(canvas)-getHeight(flower1)-5)

#Second picture, 100 pixels over

copy(flower2,canvas,100,getHeight(canvas)-getHeight(flower2)-5)

#Third picture, flower1 negated negative(flower1)

copy(flower1,canvas,200,getHeight(canvas)-getHeight(flower1)-5)

#Fourth picture, flower2 with no blue clearBlue(flower2)

copy(flower2,canvas,300,getHeight(canvas)-getHeight(flower2)-5)

#Fifth picture, flower1, negated with decreased red

decreaseRed(flower1)

copy(flower1,canvas,400,getHeight(canvas)-getHeight(flower2)-5)

return canvas

Page 21: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

Rotating the copydef flipHorseSideways(): # Set up the source and target pictures src = makePicture("horse.jpg") canvas = makeEmptyPicture(1000,1000) # Now, do the actual copying targetX = 0 for sourceX in range(0,getWidth(src)): targetY = 0 for sourceY in range(0,getHeight(src)): color = getColor(getPixel(src,sourceX,sourceY)) # Change is here setColor(getPixel(canvas,targetY,targetX), color) targetY = targetY + 1 targetX = targetX + 1 show(canvas) return canvas

Page 22: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

Rotating: How it worksWe increment the

same, but we use targetX for the Y coordinate and targetY for the X coordinate

Page 23: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

Rotate: How it endsSame amount of

increment, even same values in the variables, but a different result.

Page 24: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

Doing a real rotation

def rotateHorseSideways(): # Set up the source and target pictures src = makePicture("horse.jpg") canvas = makeEmptyPicture(1000,1000) # Now, do the actual copying targetX = 0 width = getWidth(src) for sourceX in range(0,getWidth(src)): targetY = 0 for sourceY in range(0,getHeight(src)): color =

getColor(getPixel(src,sourceX,sourceY)) # Change is here setColor(getPixel(canvas,targetY,width -

targetX - 1), color) targetY = targetY + 1 targetX = targetX + 1 show(canvas) return canvas

Page 25: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

ScalingScaling a picture (smaller or larger) has to do

with sampling the source picture differentlyWhen we just copy, we sample every pixelIf we want a smaller copy, we skip some pixels

We sample fewer pixelsIf we want a larger copy, we duplicate some

pixels We over-sample some pixels

Page 26: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

Scaling the horse face downdef copyHorseFaceSmaller(): # Set up the source and target pictures src=makePicture("horse.jpg") canvas = makeEmptyPicture(82,155) # Now, do the actual copying sourceX = 104 for targetX in range(0,int(163/2)): sourceY = 114 for targetY in range(0,int(308/2)): color = getColor(getPixel(src,sourceX,sourceY)) setColor(getPixel(canvas,targetX,targetY), color) sourceY = sourceY + 2 sourceX = sourceX + 2 show(canvas) return canvas

Page 27: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

Scaling the picture downdef copyBarbsFaceSmaller(): # 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 sourceX = 45 for targetX in range(100,100+((200-45)/2)): sourceY = 25 for targetY in range(100,100+((200-25)/2)): color = getColor(getPixel(barb,sourceX,sourceY)) setColor(getPixel(canvas,targetX,targetY), color) sourceY = sourceY + 2 sourceX = sourceX + 2 show(barb) show(canvas) return canvas

Page 28: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

Scaling Up: Growing the pictureTo grow a picture, we

simply duplicate some pixels

We do this by incrementing by 0.5, but only use the integer part.

>>> print int(1)1>>> print int(1.5)1>>> print int(2)2>>> print int(2.5)2

Page 29: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

Scaling up

def copyHorseLarger(): # Set up the source and target pictures src = makePicture("horse.jpg") w = getWidth(src) h = getHeight(src) canvas = makeEmptyPicture(w*2,h*2) srcPixels = getPixels(src) trgPixels = getPixels(canvas) trgIndex = 0 # Now, do the actual copying for pixel in srcPixels: color = getColor(pixel) # Once trgPixel = trgPixels[trgIndex] setColor(trgPixel,color) trgIndex = trgIndex + 1 # Twice trgPixel = trgPixels[trgIndex] setColor(trgPixel,color) trgIndex = trgIndex + 1 show(canvas) return canvas

Page 30: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

Scaling up just the Facedef copyHorseFaceLarger(): # Set up the source and target pictures src=makePicture("horse.jpg") canvas = makeEmptyPicture(163*2,308*2) # Now, do the actual copying sourceX = 104 for targetX in range(0,163*2): sourceY = 114 for targetY in range(0,308*2): srcpx = getPixel(src,int(sourceX),int(sourceY)) color = getColor(srcpx) setColor(getPixel(canvas,targetX,targetY), color) sourceY = sourceY + 0.5 sourceX = sourceX + 0.5 show(canvas) return canvas

Page 31: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

Scaling the picture updef copyBarbsFaceLarger(): # 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 sourceX = 45 for targetX in range(100,100+((200-45)*2)): sourceY = 25 for targetY in range(100,100+((200-25)*2)): color = getColor(getPixel(barb,int(sourceX),int(sourceY))) setColor(getPixel(canvas,targetX,targetY), color) sourceY = sourceY + 0.5 sourceX = sourceX + 0.5 show(barb) show(canvas) return canvas

Page 32: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

Scaling up: How it worksSame basic setup as

copying and rotating:

Page 33: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

Scaling up: How it works 2But as we increment

by only 0.5, and we use the int() function, we end up taking every pixel twice.

Here, the blank pixel at (0,0) in the source gets copied twice onto the canvas.

Page 34: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

Scaling up: How it works 3Black pixels gets

copied once…

Page 35: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

Scaling up: How it works 4And twice…

Page 36: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

Scaling up: How it ends upWe end up in the

same place in the source, but twice as much in the target.

Notice the degradation: Gaps that weren't there

previously Curves would get “choppy”:

Pixelated

Page 37: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

What to do?How do we clear up the degradation of

scaling up?Variety of techniques, but mostly following

the same basic idea:Use the pixels around to figure out what color

a new pixel should be, then somehow (e.g., by averaging) compute the right color.

Different techniques look at different pixels and compute different averages in different ways.

Page 38: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

A simple Blurdef blur(source): target=duplicatePicture(source) for x in range(1, getWidth(source)-1): for y in range(1, getHeight(source)-1): top = getPixel(source,x,y-1) left = getPixel(source,x-1,y) bottom = getPixel(source,x,y+1) right = getPixel(source,x+1,y) center = getPixel(target,x,y) newRed=(getRed(top)+ getRed(left) + getRed(bottom) + getRed(right) + getRed(center))/5 newGreen=(getGreen(top) + getGreen(left) + getGreen(bottom)+getGreen(right)+getGreen(center))/5 newBlue=(getBlue(top) + getBlue(left) + getBlue(bottom) + getBlue(right)+ getBlue(center))/5 setColor(center, makeColor(newRed, newGreen, newBlue))

Page 39: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

A different blurdef blur(pic,size): for pixel in getPixels(pic): currentX = getX(pixel) currentY = getY(pixel) r = 0 g = 0 b = 0 count = 0 for x in range(currentX - size,currentX + size): for y in range(currentY - size, currentY + size): if(x<0) or (y<0) or (x >= getWidth(pic)) or (y

>=getHeight(pic)): pass # Skip if we go off the edge else: r = r + getRed(getPixel(pic,x,y)) g = g + getGreen(getPixel(pic,x,y)) b = b + getBlue(getPixel(pic,x,y)) count = count + 1 newColor = makeColor(r/count,g/count,b/count) setColor(pixel,newColor)

We'll see pass and else later, but you can probably get a sense here of what's going on.

Page 40: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

Blurring out the pixelation

Page 41: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

Average from four sides, to compute new color

Page 42: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

Things to try:Can you come up with general copy, rotate,

copy, and scale functions?Take input pictures and parametersReturn the canvas the correct transformation

appliedAlso think about generalizing the

transformations:Scaling up and down by non-integer amountsRotating by something other than 90 degree

increments

Page 43: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

Blending picturesHow do we get part of one picture and part of

another to blur together, so that we see some of each?It's about making one a bit “transparent.”Video cards sometimes support this transparency

in hardware, called an alpha level to each pixel.We do it as a weighted sum

If it's 50-50, we take 50% of red of picture1's pixels + 50% of red of picture2's pixels, and so on for green and blue, across all overlapping pixels.

Page 44: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

Example blended picture

Blended here

Page 45: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

Blending code (1 of 3)def blendPictures(): barb = makePicture(getMediaPath("barbara.jpg")) katie = makePicture(getMediaPath("Katie-smaller.jpg")) canvas = makePicture(getMediaPath("640x480.jpg")) #Copy first 150 columns of Barb sourceX=0 for targetX in range(0,150): sourceY=0 for targetY in range(0,getHeight(barb)): color = getColor(getPixel(barb,sourceX,sourceY)) setColor(getPixel(canvas,targetX,targetY),color) sourceY = sourceY + 1 sourceX = sourceX + 1

Straightforward copy of 150 column's of Barb's picture

Page 46: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

Blending code (2 of 3) #Now, grab the rest of Barb and part of Katie # at 50% Barb and 50% Katie overlap = getWidth(barb)-150 sourceX=0 for targetX in range(150,getWidth(barb)): sourceY=0 for targetY in range(0,getHeight(katie)): bPixel = getPixel(barb,sourceX+150,sourceY) kPixel = getPixel(katie,sourceX,sourceY) newRed= 0.50*getRed(bPixel)

+0.50*getRed(kPixel) newGreen=0.50*getGreen(bPixel)

+0.50*getGreen(kPixel) newBlue = 0.50*getBlue(bPixel)

+0.50*getBlue(kPixel) color = makeColor(newRed,newGreen,newBlue) setColor(getPixel(canvas,targetX,targetY),color) sourceY = sourceY + 1 sourceX = sourceX + 1

Here's the trick. For each pixel, grab 50% of each red, green and blue

Page 47: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

Blending code (3 of 3) # Last columns of Katie sourceX=overlap for targetX in

range(150+overlap,150+getWidth(katie)): sourceY=0 for targetY in range(0,getHeight(katie)): color = getColor(getPixel(katie,sourceX,sourceY)) setColor(getPixel(canvas,targetX,targetY),color) sourceY = sourceY + 1 sourceX = sourceX + 1 show(canvas) return canvas

Page 48: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

Drawing lines on Carolina

def lineExample():

img = makePicture(pickAFile())

verticalLines(img)

horizontalLines(img)

show(img)

return img

 

def horizontalLines(src):

for x in range(0,getHeight(src),5):

for y in range(0,getWidth(src)):

setColor(getPixel(src,y,x),black)

 

def verticalLines(src):

for x in range(0,getWidth(src),5):

for y in range(0,getHeight(src)):

setColor(getPixel(src,x,y),black)

We can use the color name “black” – it's pre-defined for us.

Page 49: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

Yes, some colors are already definedColors defined for you already: black, white,

blue, red, green, gray, lightGray, darkGray, yellow, orange, pink, magenta, and cyan

Page 50: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

That's tediousThat's slow and tedious to set every pixel you

want to make lines and text, etc.What you really want to do is to think in

terms of your desired effect (think about “requirements” and “design”)

Page 51: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

New functionsaddText(pict,x,y,string) puts the string

starting at position (x,y) in the pictureaddLine(picture,x1,y1,x2,y2) draws a line

from position (x1,y1) to (x2,y2)addRect(pict,x1,y1,w,h) draws a black

rectangle (unfilled) with the upper left hand corner of (x1,y1) and a width of w and height of h

addRectFilled(pict,x1,y1,w,h,color) draws a rectangle filled with the color of your choice with the upper left hand corner of (x1,y1) and a width of w and height of h

Page 52: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

The mysterious red box on the beachdef addABox(): beach = makePicture(getMediaPath("beach-

smaller.jpg")) addRectFilled(beach,150,150,50,50,red) show(beach) return beach

Page 53: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

Example picturedef littlepicture(): canvas=makePicture(getMediaPath("640x480.jpg")) addText(canvas,10,50,"This is not a picture") addLine(canvas,10,20,300,50) addRectFilled(canvas,0,200,300,500,yellow) addRect(canvas,10,210,290,490) return canvas

Page 54: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

A thought experimentLook at that previous page: Which has a

fewer number of bytes?The program that drew the pictureThe pixels in the picture itself.

It's a no-brainerThe program is less than 100 characters (100

bytes)The picture is stored on disk at about 15,000

bytes

Page 55: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

Vector-based vs. Bitmap Graphical representationsVector-based graphical representations are

basically executable programs that generate the picture on demand.Postscript, Flash, and AutoCAD use vector-

based representationsBitmap graphical representations (like JPEG,

BMP, GIF) store individual pixels or representations of those pixels.JPEG and GIF are actually compressed

representations

Page 56: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

Vector-based representations can be smallerVector-based representations can be much

smaller than bit-mapped representationsSmaller means faster transmission (Flash and

Postscript)If you want all the detail of a complex picture,

no, it's not.

Page 57: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

But vector-based has more value than that

Imagine that you're editing a picture with lines on it. If you edit a bitmap image and extend a line, it's just more bits.

There's no way to really realize that you've extended or shrunk the line.

If you edit a vector-based image, it's possible to just change the specification Change the numbers saying where the line is Then it really is the same line

That's important when the picture drives the creation of the product, like in automatic cutting machines

Page 58: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

How are images compressed?Sometimes lossless using techniques like run

length encoding (RLE)Instead of this:

B B Y Y Y Y Y Y Y Y Y B BWe could say “9 Y's” like this:

B B 9 Y B BLossy compression (like JPEG and GIF) loses detail, some

of which is invisible to the eye.

Page 59: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

When changing the picture means changing a program…In a vector-based drawing package, changing

the drawing is changing a program.How could we reach in and change the actual

program?We can using string manipulation

The program is just a string of charactersWe want to manipulate those characters, in

order to manipulate the program

Page 60: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

Example programmed graphicIf I did this right, we

perceive the left half as lighter than the right half

In reality, the end quarters are actually the same colors.

Page 61: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

Building a programmed graphicdef greyEffect(): file = getMediaPath("640x480.jpg") pic = makePicture(file) # First, 100 columns of 100-grey grey = makeColor(100,100,100) for x in range(1,100): for y in range(1,100): setColor(getPixel(pic,x,y),grey) # Second, 100 columns of increasing greyness greyLevel = 100 for x in range(100,200): grey = makeColor(greyLevel, greyLevel, greyLevel) for y in range(1,100): setColor(getPixel(pic,x,y),grey) greyLevel = greyLevel + 1

# Third, 100 colums of increasing greyness, from 0 greyLevel = 0 for x in range(200,300): grey = makeColor(greyLevel, greyLevel, greyLevel) for y in range(1,100): setColor(getPixel(pic,x,y),grey) greyLevel = greyLevel + 1 # Finally, 100 columns of 100-grey grey = makeColor(100,100,100) for x in range(300,400): for y in range(1,100): setColor(getPixel(pic,x,y),grey) return pic

Page 62: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

Another Programmed Graphicdef coolpic():

canvas=makePicture(getMediaPath("640x480.jpg"))

for index in range(25,1,-1): color = makeColor(index*10,index*5,index)

addRectFilled(canvas,0,0,index*10,index*10,color) show(canvas) return canvas

Page 63: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

And anotherdef coolpic2(): canvas=makePicture(getMediaPath("640x480.jpg")) for index in range(25,1,-1): addRect(canvas,index,index,index*3,index*4)

addRect(canvas,100+index*4,100+index*3,index*8,index*10)

show(canvas) return canvas

Page 64: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

Why do we write programs?Could we do this in Photoshop? Maybe

I'm sure that you can, but you need to know how.

Could I teach you to do this in Photoshop? MaybeMight take a lot of demonstration

But this program is an exact definition of the process of generating this pictureIt works for anyone who can run the program,

without knowing Photoshop

Page 65: Copying: How it works Here's the initial setup:. Copying: How it works 2 After incrementing the sourceY and targetY once (whether in the for or via expression):

We write programs to encapsulate and communicate processIf you can do it by hand, do it.If you need to teach someone else to do it,

consider a program.If you need to explain to lots of people how to

do it, definitely use a program.If you want lots of people to do it without

having to teach them something first, definitely use a program.