Milestone 4 of 8

Implement brightness and masks safely

Use wider signed arithmetic and clipping for brightness, validate boolean mask and fill shapes, and preserve every unmasked pixel exactly.

Unsigned pixel values have a trap: adding to uint8 can wrap around instead of reaching the next valid value. Make the arithmetic and mask contract explicit.

Goal

Implement overflow-safe brightness adjustment and boolean masks while preserving unmasked pixels, channel shape, and uint8 output.

Operations

Implement:

adjust_brightness(image, delta)
apply_mask(image, mask, fill_values)

Require an integer delta from -255 through 255. Calculate brightness in a wider signed dtype, clip to [0, 255], and convert back to uint8. Require a boolean mask of shape (height, width) and one fill value from 0 through 255 per channel. Replace masked pixels only; preserve every unmasked pixel.

Deliverables

Extend src/operations.py with both operations. Save exact pixel checks for zero, positive, and negative deltas, clipping boundaries, an all-false and an all-true mask, and one mask with different fill values per RGB channel.

Checks

Use pixels at 0, 1, 254, and 255. Check positive and negative clipping and prove that no value wraps around. Reject non-integer and out-of-range deltas. Reject masks with the wrong shape or dtype and invalid fill length or values. Check that masked pixels receive the configured values, unmasked pixels are identical, and source arrays remain unchanged.

Run each operation twice and compare exact arrays. Check grayscale and RGB arrays, including a length-one channel axis. Do not treat a nonzero integer mask as a boolean mask by coercion.

Workspace

Keep arithmetic, validation, and mask checks in src/operations.py. The local mean filter belongs to the next milestone.

Hints

HintWiden before adding
If a pixel is 255 and delta=1, calculate 255 + 1 in a signed type, clip it to 255, then convert.
HintThe mask has no channel axis
One boolean per row and column selects a whole pixel. Fill values supply the channel values for that pixel.

Review

Which result would an unchecked uint8 addition produce for 255 plus 1? Pick one masked RGB pixel and explain why all its channels change together.

How to check your work

Checks compare extreme-value tables, clipping, mask shape checks, unmasked equality, and source immutability with the fixtures. The operations do not claim to make an image brighter in a perceptual sense.

LLM PrimerImplement brightness and masks safelyhttps://llmprimer.com/python/projects/build-an-image-transformation-toolkit/implement-brightness-and-masks-safely© 2026 LLM Primer