< CS106A

Today: swap, int math, += shortcut, nested-loop image algorithms

PSA - What is "done" for a homework?

• Tempting: well the output is right, so I'm done!
• You should understand why every line is there
• e.g. select code, delete it all
Re-create the whole thing?
• The exam will look like the HW...

Thought For the Day: Image - Numbers - Code

• Layers of understanding
• 1. See An image - anyone can do that!
• 2. Understand structure of numbers, red/green/blue etc. making an image
• 3. Write code to change the numbers, changing the image .. CS106A!

Python Interpreter

Python Guide: Py Interpreter

Type code directly into Python at a `>>>` prompt, see what it produces. Very handy way to explore; we'll use this below to see how computer math works.

On parlante.org, use the hack mode interpreter page

```>>> 23 + 6    # user types this
29            # see result
```

Math

For details, see Python Guide: Py Math

int and float

• Two types of number "int" and "float"
• int `5, 23, -6`
• int mathematics is "precise"
Like formal mathematics
3 + 4 is exactly == 7, as is 4 + 3
• float `3.14, 1.2e23`
• float: has a dot "." when printed
• Surprisingly, float is not totally precise (later)

Math Operators: + - * /

• Usual math operators + - * /
• Precedence: * / go before + -
• Otherwise evaluation goes left-right
• Try in the interpreter
• Up Arrow Power!
```>>> 2 + 3
5
>>> 2 + 3 * 4  # precedence
14
```

Division / → float

• Division is tricky
• `a / b` returns a float value, not an int
• Even if the division comes out even
• What if we want an int?
```>>> 7 / 2
3.5
>>> 8 / 2
4.0
```

Int Division // → int

• `a // b` int division operator
• Returns an int value by always rounding down to the next int
```>>> 7 // 2
3
>>> 8 // 2
4
```

Relative Variable Change

Common "relative" pattern for a variable:

```x = x + 1
```

Above increases the value of x by 1

e.g. Suppose x is 6. (1) First evaluate the right hand side, which comes to 7. (2) Then assign the 7 into x. This resolves the circularity with x appearing on both left and right by handling the right side first.

Relative Variable Shortcut: += *= //=

Shortcut operator to update a var: `+=`. The following is just a shorthand for `x = x + 1`

```x += 1
```

Here's a shorthand for `x = x * 2`

```x *= 2  # double x
```
• Works for all operators, such as `+= -= //=`
• Handy because relative math on a var is so common
• This just make the code more compact
```>>> x = 10
>>> x += 3
>>> x
13
>>> x //= 2
>>> x
6
```

Image For Loop Structure

```def red_channel(filename):
image = SimpleImage(filename)
for pixel in image:
pixel.green = 0
pixel.blue = 0
return image
```
• Filename is like 'flowers.jpg'
• `image = ...` line loads image data into memory
• `image` is a variable, points to image data
• `for` loop - most useful, run loop once per item
aka "foreach" loop
• for loop, runs `pixel` variable over pixels
• `pixel` is a variable, points to next pixel each time
• `return image` - "return" passes information back to our caller
• `return` is the companion to parameters
• Parameter = information from caller to called
• Return = information sent back from called to caller

Image1 Code Demos

> Image1 Functions
• Demo red_channel()
• Experiment: green channel, make every pixel black
• Demo darker()
• See how for loop runs over the image
• See how `pixel.red` accesses red/green/blue numbers
• for loop is known as - "for each"

Image2 Puzzles

> Image2 Puzzles
• Loop over image, write code to change pixels - "foreach" loop
• a. recover hidden image
• b. 5-10-20 puzzle
5-10-20 puzzle: red, green, and blue values are too small by a factor of 5 10 20. But we do not know which factor goes with which color. Figure it out by experimenting with code to modify the image with various factors.

Swap

• A little code pattern everyone should know
• Exchange the values in 2 variables
• Standard, idiomatic 3-line "temp" sequence
• Be able to draw what's going on with memory
• Mnemonic: temp=var, then var=... (rest sort of follows)
• Trying this in hack-mode
```>>> x = 1
>>> y = 2
>>> x
1
>>> y
2
>>> temp = x
>>> x = y
>>> y = temp
>>> x
2
>>> y
1
```

After the above swap finishes:

Image Coordinates

Load image into memory like this

```image = SimpleImage(filename)
```
• image.width, image.height - int number of pixels
e.g. image.width is 200, image.height is 100
(like pixel.red - these are Python "properties")
• Origin x=0 y=0 is at upper left
• x grows right
• y grows down
• This coordinate scheme is like typesetting lines of text
• Say width is 100, what is range of x values?
• 0..99 inclusive (max x is 1 less than width)
• width 100, height 50 drawing, (x, y) pixels:
(0, 0) pixel at upper left
(99,0) at upper right
(99, 49) at lower right
• In all these examples x,y are int
There's no pixel at x=2.5 !

for x in range(10):

• Today: want to write a loop where x = 0, 1, 2, 3, ....
• 1-parameter range(n) function
• range(10) represents the series:
0, 1, 2, ... 8, 9
• Start at 0, go up to but not including the n parameter
• range(n) = 0, 1, ... n-1
• range(n) works in a foreach loop
• Handy for accessing pixels on next examples!
```# "list" is required here to display range
# as number series in brackets
>>> list(range(10))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> list(range(5))
[0, 1, 2, 3, 4]
>>> list(range(1))       # just number 0
[0]
>>> list(range(0))       # no numbers!
[]
>>> for x in range(10):  # "foreach" works
...   print(x)
...
0
1
2
3
4
5
6
7
8
9
```

Strategy Note: Detail Oriented

• Book: Thinking Fast and Slow, by Kahneman
• Mostly your brain is not paying much attention and that's fine
• Problem (c) below
Your really need to slow down and work the details
• Sometimes computer code requires detail oriented approach
• There is no other strategy

4 Image Range Problems

a. and b. are examples, c. is a key example, d. we may get to. > Image Range1

Previously we used foreach to access every pixel. Here we'll use nested-range loops - another form of iteration.

Understanding nested loops is step up in programming power.

a. Darker image-range Example

• image.get_pixel(x, y) function - returns pixel for x,y vals
• Nested range loops
outer and inner loops
• Canonical range-loop code
• Loop does top row left-right, then next row, ... like reading text
• y = 0 outer loop, inner loop x goes through whole range
• then y = 1 outer, inner loop x goes through whole range again
• try in loop: print('x:', x, 'y:', y)
only do this with small images like we have here
otherwise its too much output
```    image = SimpleImage(filename)
for y in range(image.height):
for x in range(image.width):
pixel = image.get_pixel(x, y)
```

Note: How to Make 2 Pixels Look The Same?

• Have pixel a
• Make pixel b look the same as a .. how?
• Pixels look the same if they have the same RGB numbers
• Make b look the same as a:
```b.red = a.red
b.green = a.green
b.blue = a.blue
```

b. mirror1

• Make a new blank image (vs. filename), here width 200, height 100:
`out = SimpleImage.blank(image.width * 2, 100)`
• This problem:
• 1. Create out twice as wide as original
• 2. Copy original image to left half
• Make a drawing, then think about the code
```def mirror1(filename):
"""
Code is provided - this is an example.
Read the original image at the given filename.
Create a new 'out' image twice as wide as the original.
Copy the original image to the left half of out, leaving
the right half blank (this is a halfway-point to the image2).
"""
image = SimpleImage(filename)
# SimpleImage.blank(width, height) - returns a new
# image with size given in its 2 parameters.
# Here, create out image with width * 2 or first image:
out = SimpleImage.blank(image.width * 2, image.height)
for y in range(image.height):
for x in range(image.width):
pixel = image.get_pixel(x, y)
# left copy
pixel_left = out.get_pixel(x, y)
pixel_left.red = pixel.red
pixel_left.green = pixel.green
pixel_left.blue = pixel.blue
# right copy
# nothing!
return out
```

c. mirror2

• This is the key exercise for today
• Same as (b) + place mirror image of original on right half
• A complex problem with coordinates, make a drawing
• Choose concrete numbers to work out an example
• e.g. say original width = 100
• Make diagram, say 3 ABC "source" points:
```What is the dest x,y for each?
A: (0, 0)
B: (1, 0)
C: (2, 0)
D: (99, 0)
```
• Figure out the formula to compute dest x,y from source x,y
• (Demo: go through points, figure out formula)
• (Demo: put in wrong formula, see bad x,y error message)
• Strategy: concrete numbers + drawing .. guide the code
• Diff slider draws yellow bars where the output seems wrong to the system
ABC Table Solution

mirror2 Solution Code

```def mirror2(filename):
"""
Like mirror1, but also copy the original image
to the right half of "out", but as a horizontally reversed
mirror image. So the left half is a regular copy,
and the right half is a mirror image.
(Starter code does the left half).
"""
image = SimpleImage(filename)
out = SimpleImage.blank(image.width * 2, image.height)
for y in range(image.height):
for x in range(image.width):
pixel = image.get_pixel(x, y)
# left copy
pixel_left = out.get_pixel(x, y)
pixel_left.red = pixel.red
pixel_left.green = pixel.green
pixel_left.blue = pixel.blue
# right copy
# this is the key spot
# have: pixel at x,y in image
# want: pixel_right at ??? to write to
pixel_right = out.get_pixel(out.width - 1 - x, y)
pixel_right.red = pixel.red
pixel_right.green = pixel.green
pixel_right.blue = pixel.blue
return out
```

Aside: Parameters

• We've talked about parameters - information passed in to a function call
• Old simple example - pass 'blue' as parameter value for call of paint() function
```  bit.paint('blue')
```
-Now we have complicated examples, like this line:
```  out.get_pixel(out.width - 1 - x, y)
```
• get_pixel(x, y) - has "x" and "y" parameters
• The above uses the expression "out.width - 1 - x"
• To provide a value for the "x" parameter
in the call of the get_pixel() function

d. shrink

• (may get to this one)
• Make out image half the width/height
• For dest pixel at x= 0 1 2 3 4 ...
• Q: what is the x source pixel to halve the size?
• Source at x= 0 2 4 6 8 ...