Images

Pixels, resolution, colour depth, metadata and file size, from the robot's camera.

F8.7Data representationGCSE15 min

Do this lesson in the simulator

A digital image is a grid of dots called pixels, and each pixel's colour is stored as a binary number. BugBot's camera works exactly like this, and camera_image() gives you its picture as a grid of numbers you can read, change and measure. This lesson looks at the robot's view pixel by pixel.

A picture is a grid of numbers

# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()

img = camera_image(16, 12)
print(len(img), "rows of", len(img[0]), "pixels")
print("top-left pixel:", img[0][0])
print("middle pixel:", img[6][8])
print("bottom-left pixel:", img[11][0])

Run this in the simulator

camera_image(width, height) returns a list of rows, and each row is a list of pixels. Each pixel is a tuple of three numbers, red, green and blue, from 0 to 255: one byte each. img[6][8] is row 6, column 8, the 2D arrays of lesson F3.5.

Seeing it in the console

Printing a character for each pixel draws the picture. Dark pixels as #, light as .:

# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()

img = camera_image(32, 24)
for row in img:
    line = ""
    for r, g, b in row:
        brightness = (r + g + b) / 3
        line = line + ("#" if brightness < 128 else ".")
    print(line)

Run this in the simulator

The top of the picture is the light room behind the mat, the dark shape across the middle is the wall, and the red and blue balls in front of it are dark too, because red and blue pixels have a low average brightness. With only 32 by 24 pixels, small things become just a few dots. Turn the robot with turn_right(30, angle=30) before camera_image to look somewhere else.

Resolution and colour depth

Two things decide how good an image looks, and how much space it takes:

  • Resolution: the number of pixels, width × height. More pixels, more detail.
  • Colour depth: the number of bits for each pixel. With n bits a pixel can be one of 2 to the power n colours.
Colour depth Colours per pixel Example
1 bit 2 black and white, like the # and . picture
8 bits 256 a greyscale photo
24 bits 16,777,216 full colour, like the camera: 8 bits each for red, green and blue

File size

The size of an image in bits is:

width × height × colour depth

# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()

def image_bits(width, height, depth):
    return width * height * depth

for w, h, depth in [(32, 24, 1), (32, 24, 24), (320, 240, 24), (1920, 1080, 24)]:
    bits = image_bits(w, h, depth)
    print(f"{w} x {h} at {depth}-bit: {bits} bits = {bits / 8 / 1000:.1f} kB")

Run this in the simulator

Double the width and the height, and the file is four times as big. A full HD photo is over 6 MB before compression.

Metadata

An image file also stores metadata: data about the image. Without its width and height, a list of pixel values could not be turned back into a picture, because the computer would not know where each row ends. Metadata often includes the colour depth, the date, the camera, and sometimes the location where a photo was taken, which is worth knowing before sharing one.

Task: camera pixels

Capture camera_image(32, 24). Print it as 24 lines of 32 characters, # for a pixel whose average of red, green and blue is below 128, . otherwise. Then print 1-bit size: <bits> and 24-bit size: <bits> for a 32 × 24 image, worked out with a calculation.

# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()

img = camera_image(32, 24)

Challenges

  1. Count how many pixels in the picture are mostly red, meaning red is more than green and blue added together.
  2. Print a greyscale picture using the characters .:-=+*#%@ from light to dark.
  3. How many bytes would 10 seconds of camera frames at 320 × 240, 24-bit and 30 frames a second take?