A Photo Is Secretly a Grid of Numbers
Take out your phone, open any photo, and pinch to zoom in. Keep going — past the face, past the eye, past the eyelash. At some point the smooth, lifelike picture stops being smooth. It breaks apart into a checkerboard of tiny coloured squares, each one a single flat tone. Those squares were always there; zooming just let you see them. Each little square is a pixel, short for 'picture element', and it is the smallest piece of an image a computer can store or show.
A smooth photo on the left; an arrow zooms into a small region shown on the right as a coarse grid of individual coloured squares, each labelled as one pixel.
A whole image is just a rectangular arrangement of these pixels, lined up in rows and columns like a wall of mosaic tiles. We call this a digital image: a picture stored as a fixed grid of pixels, where every pixel holds one or more numbers describing its colour or brightness. Think of a spreadsheet, or a sheet of graph paper — every cell of the grid contains a number, and that number is what the pixel 'is' to the computer.
Because it is a grid, we can give every pixel an address using two numbers: which row it sits in and which column it sits in — exactly like naming a seat by its row and seat number in a cinema. We will use this row/column addressing for the rest of this track, so let us fix it now: a grid that is W pixels wide and H pixels tall has H rows stacked top to bottom and W columns running left to right. Each (row, column) pair points at exactly one pixel.
Grayscale: One Number per Pixel
Colour adds a layer of complication, so let us start with the simplest possible image and add colour only in the next guide. In a black-and-white photo — more precisely a grayscale image — every pixel stores just a single number: its brightness. One pixel, one number. No hue, no colour, just 'how light or dark is this square?'
By far the most common convention is to let that brightness number run from 0 to 255. 0 means fully black (no light), 255 means fully white (maximum light), and every value in between is a shade of gray — 64 is a dark gray, 128 is a middle gray, 200 is a light gray. Why 255 of all numbers, and not 100 or 1000? That oddly specific ceiling comes from how many bits each pixel is given, which is the topic of the very next section. For now, just take 0–255 as the standard ruler for brightness.
# A tiny 4x4 grayscale image, written as a grid of brightness values.
# 0 = black, 255 = white. Each number is ONE pixel.
image = [
[ 0, 0, 255, 255], # row 0: two black squares, then two white
[ 0, 128, 128, 255], # row 1: black, two mid-grays, white
[255, 128, 128, 0], # row 2: white, two mid-grays, black
[255, 255, 0, 0], # row 3: two white squares, then two black
]
# image[row][col] looks up the brightness of one pixel.
print(image[1][2]) # -> 128, the mid-gray pixel in row 1, column 2Read that table the way a computer would. The top row is black, black, white, white, so the top-left of the picture is dark and the top-right is bright. Drop to the next rows and the bright and dark squares swap corners, with soft mid-gray (128) values forming a square in the middle. If you printed each number as a shaded square, you would see a little X-like pattern of light and dark. That is the whole trick: the number controls the brightness of the square, so a table of numbers becomes a picture you can see.
Bit Depth: How Many Shades Can a Pixel Hold?
We keep meeting the number 256 (the count of values from 0 to 255). Where does it come from? It comes from bit depth: the number of bits a pixel is given to store its value. A bit is a single binary digit — a switch that is either 0 or 1. The more bits each pixel gets, the more distinct brightness levels it can represent.
Picture brightness as a staircase from black up to white. Bit depth decides how many steps the staircase has. With only a few steps, a smooth sky has to jump abruptly from one gray to the next, and you see ugly stripes — called banding or posterization. With many steps, the jumps are so small the gradient looks perfectly smooth to the eye. More bits = more steps = smoother shading; fewer bits = coarse, visibly stepped tones. A grayscale image is one channel of exactly this kind.
The number of brightness levels L doubles with every extra bit b.
Read this as 'the number of available levels equals two raised to the power of the bit count.' Symbol by symbol: L is the number of distinguishable brightness values a pixel can take; b is the number of bits given to that pixel; and the base 2 appears because each bit is a binary on/off switch, so adding one more bit doubles the number of combinations. One bit has 2 settings; two bits have 2×2 = 4; three bits have 2×2×2 = 8. Each new bit literally doubles your choices, which is why the count grows so fast.
- 1-bit: L = 2^1 = 2 levels. Only 0 and 1 — pure black or pure white, no gray at all. This is a fax-machine or line-art look.
- 2-bit: L = 2^2 = 4 levels. Black, dark gray, light gray, white. Better, but a sky would still show obvious bands.
- 8-bit: L = 2^8 = 256 levels. Smooth enough that the eye rarely sees steps. This is the everyday standard, and its 256 levels are numbered 0 to 255.
And there is the answer to the riddle from the previous section. The familiar 0–255 range is simply the 256 levels of an 8-bit pixel. We count from 0, not 1, so the lowest value is 0 (black) and the highest is 256 − 1 = 255 (white). 8 bits per pixel is so common that when someone says 'an 8-bit grayscale image' you can immediately picture a grid of whole numbers, each between 0 and 255.
Resolution: How Many Pixels, and Why It Matters
So far we have talked about what one pixel holds. Now: how many pixels are there? That count is the image's resolution, written as width × height in pixels — for example 1920 × 1080. The first number is how many pixels across (columns), the second is how many down (rows). A higher-resolution grid has more, smaller samples of the scene, so it captures finer detail — but it also means more numbers to store and process.
Total pixel count is width times height.
This says the total number of pixels equals the width multiplied by the height. N is the total pixel count; W is the width in pixels (how many columns); H is the height in pixels (how many rows). It is just counting the cells of a grid: a grid 1920 wide and 1080 tall holds N = 1920 × 1080 = 2,073,600 pixels — about 2.07 million. That 'two million pixels' is exactly what a camera means when it advertises '2 megapixels' (mega = million).
One trap to sidestep: pixel resolution is not the same as print size. The grid 1920 × 1080 fixes how many samples you have, full stop. How big it looks on paper depends on DPI (dots per inch) — how tightly you pack those pixels when printing. The same 1920 × 1080 image can be a crisp 5-inch print or a blurry poster, depending only on how far apart you spread the pixels. Pixel count is about information captured; DPI is about physical size on output. We mostly care about the former.
Uncompressed size in bytes: pixels times channels times bytes-per-value.
This estimates how many bytes an uncompressed image takes. W × H is the pixel count N we just found. C is the number of channels — the numbers stored per pixel; for a grayscale image C = 1 (one brightness value), and you will see C = 3 for colour in the next guide. b is the bit depth, and we divide b by 8 because there are 8 bits in a byte, converting 'bits per value' into 'bytes per value.' Run the example: a 1920 × 1080, 8-bit grayscale image needs about 2,073,600 × 1 × (8/8) = 2,073,600 bytes ≈ 2.07 MB. Switch to 3-channel colour and it roughly triples to about 6.2 MB — which is why colour photos and big resolutions eat memory so fast.
From Numbers Back to Pictures: The Mental Model
Let us tie the whole guide into one durable mental model you will lean on for the rest of this ladder. An image is a grid of numbers, and the clean way to say that is: an image is a function that takes a location and returns the value stored there. The computer keeps it as a 2-D array (a table), exactly like the Python grid we wrote earlier, and 'looking at the picture' is really just reading numbers out of that table.
An image as a function: give it a column x and a row y, it returns that pixel's value.
Do not let the function notation scare you — it is just shorthand for 'look up the number at this grid cell.' I is the image itself; (x, y) is one pixel's address; and the output I(x, y) is the value stored there — for a grayscale image, a single brightness between 0 and 255. So I(2, 1) = 128 simply means 'the pixel in column 2, row 1 holds the value 128.' Nothing more mysterious than that. We are giving the lookup a name so we can talk about it cleanly later.
One convention trips up almost every beginner, so pin it down now. In images the origin (0, 0) sits at the top-left corner, not the bottom-left you may remember from math class. x is the column index and increases to the right; y is the row index and increases downward. So as y grows you move down the picture, not up. This matches how a screen draws rows top to bottom, and it is the convention nearly every image library uses. In a W × H image, x runs from 0 to W − 1 and y runs from 0 to H − 1.
A labelled pixel grid with the origin marked at the top-left, an x-axis pointing right along the columns and a y-axis pointing down along the rows, with one highlighted cell showing its (x, y) address and stored number.