Easier to read with cream paper, a tint, more contrast or larger text? Choose your colours and text, once, for every page.

Free lesson

Pixels, coordinates and drawing a line

After this lesson: I can place pixels on a grid with x and y coordinates and draw a straight line by stepping.

55 min lesson3 commandsComputer vision lab: pixels, thresholds and counting objects in JupyterLab

A screen is a grid of pixels

Computer graphics is the craft of making a picture from numbers. Everything on a screen is a grid of pixels, and a program draws by choosing which pixels to colour.

In this lesson you place a pixel with two coordinates, then draw a straight line the way graphics software does, by stepping along the grid.

By the end of this lesson

Note

I can place pixels on a grid with x and y coordinates and draw a straight line by stepping.

Key words

WordWhat it meansExample
Pixelone dot of the picture
Coordinatestwo numbers, x and y, that name a pixel(3, 2)
Originthe corner where x and y are both 0
Slopehow far a line rises for each step across
Rasteriseto turn a shape into pixels

The cells students fill in are left blank in this preview.

A pixel has an x and a y

A picture is a grid of pixels. The origin, where x and y are both 0, is the top left corner. The number x counts pixels across to the right, and y counts pixels down.

Down is the part that surprises people, because a maths graph counts y upwards. A screen starts at the top and works down, so row 0 is the top row.

Worked example: pixels in a picture

Pixelx (across)y (down)Position in a flat list
Top left000
Top right505
Second row, third pixel218
Bottom right5323

The cells students fill in are left blank in this preview.

A grid can be one flat list

Memory is a single row of boxes, so a picture is often stored row after row in one list. The pixel at x, y sits at position y times the width, plus x.

In the table, the second row starts at position 6, because the first row used 6 places. Its third pixel, x of 2, is at 6 + 2 = 8.

Make a tiny picture with Pillow

Command
docker exec jupyter python3 -c "from PIL import Image; p = Image.new('RGB', (4, 3), (10, 20, 30)); p.putpixel((3, 2), (255, 0, 0)); print(p.size, p.getpixel((0, 0)), p.getpixel((3, 2)))"

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Pillow makes a picture and sets a pixel

The Run above makes a picture 4 pixels wide and 3 high, filled with the colour (10, 20, 30). It colours the pixel at x of 3 and y of 2 red, then reads two pixels back.

It prints (4, 3) (10, 20, 30) (255, 0, 0). Pillow takes the pixel as (x, y), across first, the same order as the table.

A line is found by stepping along x

A straight line has a slope: the rise in y divided by the run in x. To rasterise it, step x one pixel at a time and work out where the line is in y.

The line rarely lands exactly on a pixel, so round y to the nearest whole number. Exactly halfway, we round up.

Worked example: a line in pixels

xExact yRounded y
000
10.671
21.331
322
42.673
53.333
644

The cells students fill in are left blank in this preview.

List the pixels of that line

Command
docker exec jupyter python3 -c "print([(x, (8 * x + 6) // 12) for x in range(7)])"

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Whole numbers avoid rounding surprises

The Run prints [(0, 0), (1, 1), (2, 1), (3, 2), (4, 3), (5, 3), (6, 4)], the same pixels as the table.

It uses only whole numbers: y is (2 times rise times step, plus run) divided by (2 times run), with //. Floating point numbers can land a hair under 0.5, and then a pixel moves.

A common mistake

Warning

Many people think stepping along x works for every line. It works only when the line is more across than up. A steep line rises faster than it runs, so one step in x jumps several rows and leaves gaps. For a steep line, step along y instead.

Draw a line in text

Code: python
width = 8
height = 5
picture = []
for y in range(height):
    picture.append(["."] * width)

# A line from (0, 0) to (7, 4). Step along x and work out y each time.
x0 = 0
y0 = 0
x1 = 7
y1 = 4
dx = x1 - x0
dy = y1 - y0
for x in range(x0, x1 + 1):
    y = y0 + (2 * dy * (x - x0) + dx) // (2 * dx)
    picture[y][x] = "#"

for row in picture:
    print("".join(row))
# Change y1 to 2, then to 0, and press Run. The line gets flatter.

Save a line as a real picture

Command
docker exec jupyter python3 -c "from PIL import Image; p = Image.new('L', (8, 5), 0); [p.putpixel((x, (8 * x + 7) // 14), 255) for x in range(8)]; p.save('line.png'); print(p.size)"

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Open line.png in JupyterLab

The Run prints (8, 5) and saves line.png in the lab's work folder. Open it from the JupyterLab file list on the left.

You see a black picture, 8 by 5 pixels, with a thin white diagonal from the top left corner down to the bottom right. It is tiny, so zoom in to see the separate pixels.

About this lab and its source: Computer vision lab: pixels, thresholds and counting objects in JupyterLab

Teaching a class? Set this module for your students with a teacher guide, marked assignments and a lab for every student.