Pixels

Calvin (Deutschbein)

W9Mon: 21 Oct

Announcements

  • Project 2: Breakout for TONIGHT 11:59 PM.
    • You should be done.
    • I will ask you if you are stuck in a minute.
  • I'll post PS5 tonight but you don't need to worry about until Wednesday. Only 2 problems.

Today

  • Pixels
    • Hexcodes
    • String operations
    • Gradients

Hexcodes

Hexcodes

  • Example: #0F0300
  • Same as:
    • R: 15
    • G: 3
    • B: 0
  • What is going on here.

Hexcodes

  • Hexcodes represent many colors as the amount of three primary colors that is present.
  • These colors are:
    • Red
    • Green
    • Blue

Hexcodes

  • Hexcodes represent the amount using a number in hexadecimal
    • Hex = 6
    • Decimal = 10
    • 6 + 10 = 16
    Hexadecimal is a way of writing down numerical values.
    • 0-9 is the same as in decimal, our number system.
    • A is like our 10
    • B is like our 11
    • ...
    • F is like our 15
    • 10 is like our 16
  • We term our number system decimal or "base ten" and this to be hexadecimal "base sixteen"

Hexcodes

  • Hexcodes represent the amount using a number in hexadecimal
    • Hex = 6
    • Decimal = 10
    • 6 + 10 = 16
    Hexadecimal is a way of writing down numerical values.
    • 0-9 is the same as in decimal, our number system.
    • A is like our 10
    • B is like our 11
    • ...
    • F is like our 15
    • 10 is like our 16
  • We term our number system decimal or "base ten" and this to be hexadecimal "base sixteen"

Hexcodes

  • Helpfully, we never have to think about this ourselves.. >>> hex(1) '0x1' >>> hex(10) '0xa' >>> hex(100) '0x64'
  • Python helpfully includes the built-in 'hex' function
    • It turns integers into strings.
    • It is like 'str()'
  • Hexadecimal is commonly prefixed with "0x" to denote it is not decimal.

Hexcodes

  • It's easier the more we look at it, but you can also just use a color picker. >>> for i in range(0x8,0x12): ... print(str(i),hex(i)) ... 8 0x8 9 0x9 10 0xa 11 0xb 12 0xc 13 0xd 14 0xe 15 0xf 16 0x10 17 0x11

Hexcodes

  • So we have:
    • The brightness of 3 colors
    • Expressed in hexadecimal.
  • What else?

Hexcodes

  • What is the brightest color possible?
  • What number does that correspond to?

Hexcodes

  • Maximum brightness is decimal 255 or hexadecimal 0xFF.
  • So:
    • W 0xFFFFFF is white
    • W 0x000000 is black
    • W 0xFF0000 is red
    • W 0x00FF00 is green
    • W 0x0000FF is blue

Hexcodes

  • So we have:
    • The brightness of 3 colors
    • Expressed in hexadecimal.
    • Up to decimal 255 or hexadecimal 0xFF.
  • For some reason, PGL (and HTML) prefix with '#' instead of '0x'

Hexcodes

    from pgl import * max = 400 colors = ['#FFFFFF','#FF0000','#00FF00','#0000FF'] gw = GWindow(max,max) x = 0 for color in colors: r = GRect(x, 0, max // 4, max) # stripe r.set_filled(True) r.set_color(color) # color it in gw.add(r) x += max // 4 # move over

Today

  • Pixels
    • ✓ Hexcodes
    • String operations
    • Gradients

Strings

  • What if we want to steadily increase brightness across the window?
  • I recommend changing size to 255 to make your life easier.
  • But basically, we need to take some numbers between 0 and 255...
  • And make a string that is 7 characters long and starts with '#' # take some colors, in red/green/blue, like: # [255, 0, 0] # and make a hexcode, like # '#FF0000' def to_color(rgbs):

Strings

  • We take a list of brightnesses...
  • ...and return a string! # take some colors, in red/green/blue, like: # [255, 0, 0] # and make a hexcode, like # '#FF0000' def to_color(rgbs:list) -> str:

Strings

  • We can say that it's a list of integers like this: # e.g. [255, 0, 0] -> '#FF0000' def to_color(rgbs:list[int]) -> str:
  • I imagine I'm saying "the things inside the list are ints"
  • This is optional.

Strings

  • First, we turn the integers into hex! # e.g. [255, 0, 0] -> '#FF0000' def to_color(rgbs:list[int]) -> str: hexes = [hex(brightness) for brightness in rgbs]
  • We can test this easily enough... >>> rgbs = [255,100,0] >>> hexes = [hex(brightness) for brightness in rgbs] >>> hexes ['0xff', '0x64', '0x0']

Strings

  • In hexcodes, each color got only two letters!
  • And there's no 0x!
  • We use `.replace` to change the 'x' to a '0' def to_color(rgbs:list[int]) -> str: hexes = [hex(brightness) for brightness in rgbs] hexes = [color.replace('x','0') for color in hexes]
  • We can test this easily enough... >>> hexes = [color.replace('x','0') for color in hexes] >>> hexes ['00ff', '0064', '000']

Strings

  • In hexcodes, each color got only two letters!
  • And there's no 0x!
  • We use slices to take the last two characters, which store the values we need! def to_color(rgbs:list[int]) -> str: hexes = [hex(brightness) for brightness in rgbs] hexes = [color.replace('x','0') for color in hexes] hexes = [color[-2:] for color in hexes] # last two
  • We can test this easily enough... >>> hexes = [color[-2:] for color in hexes] >>> hexes ['ff', '64', '00']

Strings

  • We need a '#' before the code, and then we're done! def to_color(rgbs:list[int]) -> str: hexes = [hex(brightness) for brightness in rgbs] hexes = [color.replace('x','0') for color in hexes] hexes = [color[-2:] for color in hexes] # last two return '#' + "".join(hexes)
  • We can test this easily enough... >>> to_color([100,0xff,255]) '#64ffff'

Strings

  • A single line is fine, if you prefer. def to_color(rgbs:list[int]) -> str: return '#' + "".join([hex(c).replace('x','0')[-2:] for c in rgbs])
  • We can test this easily enough... >>> to_color([0,16,0x20]) '#001020'

Today

  • Pixels
    • ✓ Hexcodes
    • ✓ String operations
    • Gradients

Gradients

  • I find solid colors ugly, so...
  • I write functions that make many rectangles of slowly changing colors.
  • A rectangle of size 1 by 1 is a pixel, the smallest unit possible.
  • I make minimally sized rectangles with minimally changing color and see what happens.

Gradients

    from pgl import * max = 255 # better than 400 - 255 is max brightness dbg = False # I had to use this a lot gw = GWindow(max,max) def my_rect(x,y,w,h,color): rect = GRect(x,y,w,h) rect.set_filled(True) rect.set_color(color) gw.add(rect) def to_color(rgbs:list[int]) -> str: return '#' + "".join([hex(c).replace('x','0')[-2:] for c in rgbs])

Gradients

  • As a first example, we can shade every pixel based on it's horizontal, 'x', or 'i' value, depending on your numbering convention. def pixel(x,y,color): my_rect(x,y,1,1,color) for i in range(max): for j in range(max): pixel(i,j,to_color([i,0,0]))
  • Basically, we have a 255 lists brightening from 0 to 255 (we show here in red only) [[0, 1, 2, ... , 254, 255], [0, 1, 2, ... , 254, 255], < 252 more such lists > [0, 1, 2, ... , 254, 255]]

Gradients

  • As a first example, we can shade every pixel based on it's horizontal, 'x', or 'i' value, depending on your numbering convention. def pixel(x,y,color): my_rect(x,y,1,1,color) [[pixel(i,j,to_color([i,j,0])) for j in range(max)] for i in range(max)]

    • Basically, we have a 255 rows of 255 columns of 3 colors, where the first color brightens left-to-right and the second color brightens top-to-bottom. [[[0,0,0], [1,0,0], ... [255,0,0]] [0,1,0], [1,1,0], ... [255,1,0]], < 252 more such lists > [0,255,0],[1,255,0], ... [255,255,0]]]



Today

  • Pixels
    • ✓ Hexcodes
    • ✓ String operations
    • ✓Gradients
  • Free bonus slides: GImage

GImage

  • You can display an image from a file in PGL using GImage(filename)
  • Joint Photographic Experts Group (JPEG):
  • `filename' should be something like:
  • fish.jpg
  • Portable Network Graphics (PNG): fish.png

GImage

  • Pick an image with a free distribution license, usually from Wikipedia.
  • That image is a link by the way.
Pixel-example
    gw = GWindow(800, 550) image = GImage("Pixel-example.png") # GNU Free image.scale(gw.get_width() / image.get_width()) gw.add(image) # can look at pixels too if you want - this will print A LOT print(image.get_pixel_array()) # this isn't neat rbg lists # more on pixel arrays next time

Announcements

  • Project 2: Breakout for TONIGHT 11:59 PM.
    • You should be done.
    • I will ask you if you are stuck in a minute.
  • I'll post PS5 tonight but you don't need to worry about until Wednesday. Only 2 problems.