Skip to content

Quantise colour before writing#1247

Merged
jamiebenstead merged 4 commits into
mainfrom
change-set_pixel-to-quantise-colour
Sep 24, 2025
Merged

Quantise colour before writing#1247
jamiebenstead merged 4 commits into
mainfrom
change-set_pixel-to-quantise-colour

Conversation

@jamiebenstead

Copy link
Copy Markdown
Contributor

closes https://github.com/RaspberryPiFoundation/digital-editor-issues/issues/871

Code used to test -

from sense_hat import SenseHat
from time import sleep

sense = SenseHat()

# --- Quantisation helper to match set_pixel ---
def quantise_rgb(r, g, b):
    r = (r >> 3) << 3
    g = (g >> 2) << 2
    b = (b >> 3) << 3
    return (r, g, b)

# --- Colours ---
colours = [
    (255, 255, 255),  # White
    (255, 0, 0),      # Red
    (0, 255, 0),      # Green
    (0, 0, 255),      # Blue
    (245, 245, 245),  # WhiteSmoke
    (220, 220, 220),  # Gainsboro
    (192, 192, 192),  # Silver
    (105, 105, 105),  # DimGray
    (169, 169, 169),  # DarkGray
    (0, 0, 0),        # Black
    (100, 149, 237),  # CornflowerBlue
    (70, 130, 180),   # SteelBlue
    (0, 0, 205),      # MediumBlue
    (25, 25, 112),    # MidnightBlue
    (0, 0, 139),      # DarkBlue
    (0, 191, 255),    # DeepSkyBlue
    (30, 144, 255),   # DodgerBlue
    (135, 206, 250),  # LightSkyBlue
    (0, 255, 255),    # Cyan
    (64, 224, 208),   # Turquoise
    (0, 128, 128),    # Teal
    (143, 188, 143),  # DarkSeaGreen
    (60, 179, 113),   # MediumSeaGreen
    (46, 139, 87),    # SeaGreen
    (0, 255, 127),    # SpringGreen
    (34, 139, 34),    # ForestGreen
    (50, 205, 50),    # LimeGreen
    (154, 205, 50),   # YellowGreen
    (128, 128, 0),    # Olive
    (85, 107, 47),    # DarkOliveGreen
    (240, 230, 140),  # Khaki
    (255, 255, 0),    # Yellow
    (255, 215, 0),    # Gold
    (184, 134, 11),   # DarkGoldenrod
    (139, 69, 19),    # SaddleBrown
    (210, 105, 30),   # Chocolate
    (255, 140, 0),    # DarkOrange
    (255, 69, 0),     # OrangeRed
    (178, 34, 34),    # Firebrick
    (255, 0, 0),      # Red
    (220, 20, 60),    # Crimson
    (255, 192, 203),  # Pink
    (255, 105, 180),  # HotPink
    (255, 20, 147),   # DeepPink
    (199, 21, 133),   # MediumVioletRed
    (153, 50, 204),   # DarkOrchid
    (148, 0, 211),    # DarkViolet
    (138, 43, 226),   # BlueViolet
    (75, 0, 130),     # Indigo
]

passed_count = 0
failed_count = 0

for c in colours:
    r, g, b = c
    sense.clear()
    sense.set_pixel(3, 3, r, g, b)

    actual = tuple(sense.get_pixel(3, 3))
    expected = quantise_rgb(r, g, b)  # match set_pixel quantization

    if actual == expected:
        print(f"✅ PASS: Requested {c} -> Quantised {expected} -> Actual {actual}")
        passed_count += 1
    else:
        print(f"❌ FAIL: Requested {c} -> Quantised {expected} -> Actual {actual}")
        failed_count += 1

    sleep(0.3)

sense.clear()

print(f"\n🎉 Tests complete! Passed: {passed_count}, Failed: {failed_count}")

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR addresses a color quantization issue in the set_pixel method to match the behavior of the actual SenseHat hardware by quantizing RGB values before writing them.

  • Added color quantization logic that reduces RGB precision to match hardware limitations
  • Updated changelog to document the behavioral change

Reviewed Changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
public/shims/sense_hat/sense_hat_blob.py Added RGB quantization logic to match hardware behavior in set_pixel method
CHANGELOG.md Added entry documenting the set_pixel quantization change

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Comment thread public/shims/sense_hat/sense_hat_blob.py
@adrian-rpf

Copy link
Copy Markdown
Contributor

@adrian-rpf adrian-rpf left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems to work well with all the colours

Comment thread CHANGELOG.md
## Unreleased

### Changed

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

extra line?

@jamiebenstead
jamiebenstead merged commit ae9412e into main Sep 24, 2025
8 checks passed
@jamiebenstead
jamiebenstead deleted the change-set_pixel-to-quantise-colour branch September 24, 2025 09:30
This was referenced Oct 13, 2025
rammodhvadia added a commit that referenced this pull request Oct 13, 2025
### Added

- Sidebar plugin functionality (#1251)

### Changed

- Changed `set_pixel` to quantise the colour before writing (#1247)
- Changed Prism config to use babel plugin enabling line highlighting
and numbering (#1254)
patch0 added a commit that referenced this pull request Feb 26, 2026
In #1247 we added code to ensure that 24-bit colour was being converted
to RGB565 (16 bit). It turns out that in the Flight Case model this was
already happening. The code was then *erroneously* multiplying the
colour values by 255. Also `set_pixels` was not quantising colours
before setting.

This PR adds in a function that is called by both `set_pixel` and
`set_pixels` to quantise the colours before setting, and updating the
internal representation of what the display contains (the
`Sk.sense_hat.pixels` array) such that `get_pixel` and `get_pixels`
return the correctly quantised colours (rather than the ones requested),
as described in the [Sense Hat library API
docs](https://pythonhosted.org/sense-hat/api/#get_pixels).

## Sample code

This code flashes through the colours on the display, and then reads
using `get_pixel` to make sure the colour set is correctly quantised. In
the console there will be a list of ✅ and ❌ marks for colours as they
pass/fail.

NB I think there is a race somewhere as the first colour (white) seems
to often fail the first run through. All the rest seem fine though 🤷🏻

```python
# Import the libraries
from sense_hat import SenseHat
from time import sleep

# Set up the Sense HAT
sense = SenseHat()
sense.set_rotation(270, False)

# --- Quantisation helper to match set_pixel ---
def check_quantise_rgb(x, y, requested):
    actual = sense.get_pixel(x, y)

    expected = [0,0,0]
    expected[0] = (requested[0] >> 3) << 3
    expected[1] = (requested[1] >> 2) << 2
    expected[2] = (requested[2] >> 3) << 3

    if actual == expected:
        print(f"✅ PASS: Requested {requested} -> Quantised {expected} -> Actual {actual}")
    else:
        print(f"❌ FAIL: Requested {requested} -> Quantised {expected} -> Actual {actual}")

colours = [
    (255, 255, 255),  # White
    (255, 0, 0),      # Red
    (0, 255, 0),      # Green
    (0, 0, 255),      # Blue
    (245, 245, 245),  # WhiteSmoke
    (220, 220, 220),  # Gainsboro
    (192, 192, 192),  # Silver
    (105, 105, 105),  # DimGray
    (169, 169, 169),  # DarkGray
    (0, 0, 0),        # Black
    (100, 149, 237),  # CornflowerBlue
    (70, 130, 180),   # SteelBlue
    (0, 0, 205),      # MediumBlue
    (25, 25, 112),    # MidnightBlue
    (0, 0, 139),      # DarkBlue
    (0, 191, 255),    # DeepSkyBlue
    (30, 144, 255),   # DodgerBlue
    (135, 206, 250),  # LightSkyBlue
    (0, 255, 255),    # Cyan
    (64, 224, 208),   # Turquoise
    (0, 128, 128),    # Teal
    (143, 188, 143),  # DarkSeaGreen
    (60, 179, 113),   # MediumSeaGreen
    (46, 139, 87),    # SeaGreen
    (0, 255, 127),    # SpringGreen
    (34, 139, 34),    # ForestGreen
    (50, 205, 50),    # LimeGreen
    (154, 205, 50),   # YellowGreen
    (128, 128, 0),    # Olive
    (85, 107, 47),    # DarkOliveGreen
    (240, 230, 140),  # Khaki
    (255, 255, 0),    # Yellow
    (255, 215, 0),    # Gold
    (184, 134, 11),   # DarkGoldenrod
    (139, 69, 19),    # SaddleBrown
    (210, 105, 30),   # Chocolate
    (255, 140, 0),    # DarkOrange
    (255, 69, 0),     # OrangeRed
    (178, 34, 34),    # Firebrick
    (255, 0, 0),      # Red
    (220, 20, 60),    # Crimson
    (255, 192, 203),  # Pink
    (255, 105, 180),  # HotPink
    (255, 20, 147),   # DeepPink
    (199, 21, 133),   # MediumVioletRed
    (153, 50, 204),   # DarkOrchid
    (148, 0, 211),    # DarkViolet
    (138, 43, 226),   # BlueViolet
    (75, 0, 130),     # Indigo
]

# First demo: sense.clear
print('Colours using sense.clear()')
sense.show_message("sense.clear", scroll_speed=0.005)
for colour in colours:
    sense.clear(colour)
    check_quantise_rgb(0,0,colour)
    sleep(0.1)

# Second demo: sense.set_pixel
print('Colours using sense.set_pixel()')
sense.clear()
sense.show_message("sense.set_pixel", scroll_speed=0.005)
x, y = [0, 0]
for colour in colours:
    sense.set_pixel(x, y, colour)
    check_quantise_rgb(x,y,colour)
    x += 1
    if x > 7:
        y += 1
        x = 0
```

## Before

Tried on
https://staging-editor-static.raspberrypi.org/branches/main/web-component.html

<img width="442" height="421" alt="image"
src="https://github.com/user-attachments/assets/ce5c98f4-7d91-4dfe-a98a-c5b13c51ff5b"
/>

Text output

```
Colours using sense.clear()
❌ FAIL: Requested (255, 255, 255) -> Quantised [248, 252, 248] -> Actual [255, 255, 255]
❌ FAIL: Requested (255, 0, 0) -> Quantised [248, 0, 0] -> Actual [255, 0, 0]
❌ FAIL: Requested (0, 255, 0) -> Quantised [0, 252, 0] -> Actual [0, 255, 0]
❌ FAIL: Requested (0, 0, 255) -> Quantised [0, 0, 248] -> Actual [0, 0, 255]
❌ FAIL: Requested (245, 245, 245) -> Quantised [240, 244, 240] -> Actual [245, 245, 245]
❌ FAIL: Requested (220, 220, 220) -> Quantised [216, 220, 216] -> Actual [220, 220, 220]
✅ PASS: Requested (192, 192, 192) -> Quantised [192, 192, 192] -> Actual [192, 192, 192]
❌ FAIL: Requested (105, 105, 105) -> Quantised [104, 104, 104] -> Actual [105, 105, 105]
❌ FAIL: Requested (169, 169, 169) -> Quantised [168, 168, 168] -> Actual [169, 169, 169]
✅ PASS: Requested (0, 0, 0) -> Quantised [0, 0, 0] -> Actual [0, 0, 0]
❌ FAIL: Requested (100, 149, 237) -> Quantised [96, 148, 232] -> Actual [100, 149, 237]
❌ FAIL: Requested (70, 130, 180) -> Quantised [64, 128, 176] -> Actual [70, 130, 180]
❌ FAIL: Requested (0, 0, 205) -> Quantised [0, 0, 200] -> Actual [0, 0, 205]
❌ FAIL: Requested (25, 25, 112) -> Quantised [24, 24, 112] -> Actual [25, 25, 112]
❌ FAIL: Requested (0, 0, 139) -> Quantised [0, 0, 136] -> Actual [0, 0, 139]
❌ FAIL: Requested (0, 191, 255) -> Quantised [0, 188, 248] -> Actual [0, 191, 255]
❌ FAIL: Requested (30, 144, 255) -> Quantised [24, 144, 248] -> Actual [30, 144, 255]
❌ FAIL: Requested (135, 206, 250) -> Quantised [128, 204, 248] -> Actual [135, 206, 250]
❌ FAIL: Requested (0, 255, 255) -> Quantised [0, 252, 248] -> Actual [0, 255, 255]
✅ PASS: Requested (64, 224, 208) -> Quantised [64, 224, 208] -> Actual [64, 224, 208]
✅ PASS: Requested (0, 128, 128) -> Quantised [0, 128, 128] -> Actual [0, 128, 128]
❌ FAIL: Requested (143, 188, 143) -> Quantised [136, 188, 136] -> Actual [143, 188, 143]
❌ FAIL: Requested (60, 179, 113) -> Quantised [56, 176, 112] -> Actual [60, 179, 113]
❌ FAIL: Requested (46, 139, 87) -> Quantised [40, 136, 80] -> Actual [46, 139, 87]
❌ FAIL: Requested (0, 255, 127) -> Quantised [0, 252, 120] -> Actual [0, 255, 127]
❌ FAIL: Requested (34, 139, 34) -> Quantised [32, 136, 32] -> Actual [34, 139, 34]
❌ FAIL: Requested (50, 205, 50) -> Quantised [48, 204, 48] -> Actual [50, 205, 50]
❌ FAIL: Requested (154, 205, 50) -> Quantised [152, 204, 48] -> Actual [154, 205, 50]
✅ PASS: Requested (128, 128, 0) -> Quantised [128, 128, 0] -> Actual [128, 128, 0]
❌ FAIL: Requested (85, 107, 47) -> Quantised [80, 104, 40] -> Actual [85, 107, 47]
❌ FAIL: Requested (240, 230, 140) -> Quantised [240, 228, 136] -> Actual [240, 230, 140]
❌ FAIL: Requested (255, 255, 0) -> Quantised [248, 252, 0] -> Actual [255, 255, 0]
❌ FAIL: Requested (255, 215, 0) -> Quantised [248, 212, 0] -> Actual [255, 215, 0]
❌ FAIL: Requested (184, 134, 11) -> Quantised [184, 132, 8] -> Actual [184, 134, 11]
❌ FAIL: Requested (139, 69, 19) -> Quantised [136, 68, 16] -> Actual [139, 69, 19]
❌ FAIL: Requested (210, 105, 30) -> Quantised [208, 104, 24] -> Actual [210, 105, 30]
❌ FAIL: Requested (255, 140, 0) -> Quantised [248, 140, 0] -> Actual [255, 140, 0]
❌ FAIL: Requested (255, 69, 0) -> Quantised [248, 68, 0] -> Actual [255, 69, 0]
❌ FAIL: Requested (178, 34, 34) -> Quantised [176, 32, 32] -> Actual [178, 34, 34]
❌ FAIL: Requested (255, 0, 0) -> Quantised [248, 0, 0] -> Actual [255, 0, 0]
❌ FAIL: Requested (220, 20, 60) -> Quantised [216, 20, 56] -> Actual [220, 20, 60]
❌ FAIL: Requested (255, 192, 203) -> Quantised [248, 192, 200] -> Actual [255, 192, 203]
❌ FAIL: Requested (255, 105, 180) -> Quantised [248, 104, 176] -> Actual [255, 105, 180]
❌ FAIL: Requested (255, 20, 147) -> Quantised [248, 20, 144] -> Actual [255, 20, 147]
❌ FAIL: Requested (199, 21, 133) -> Quantised [192, 20, 128] -> Actual [199, 21, 133]
❌ FAIL: Requested (153, 50, 204) -> Quantised [152, 48, 200] -> Actual [153, 50, 204]
❌ FAIL: Requested (148, 0, 211) -> Quantised [144, 0, 208] -> Actual [148, 0, 211]
❌ FAIL: Requested (138, 43, 226) -> Quantised [136, 40, 224] -> Actual [138, 43, 226]
❌ FAIL: Requested (75, 0, 130) -> Quantised [72, 0, 128] -> Actual [75, 0, 130]
Colours using sense.set_pixel()
✅ PASS: Requested (255, 255, 255) -> Quantised [248, 252, 248] -> Actual [248, 252, 248]
✅ PASS: Requested (255, 0, 0) -> Quantised [248, 0, 0] -> Actual [248, 0, 0]
✅ PASS: Requested (0, 255, 0) -> Quantised [0, 252, 0] -> Actual [0, 252, 0]
✅ PASS: Requested (0, 0, 255) -> Quantised [0, 0, 248] -> Actual [0, 0, 248]
✅ PASS: Requested (245, 245, 245) -> Quantised [240, 244, 240] -> Actual [240, 244, 240]
✅ PASS: Requested (220, 220, 220) -> Quantised [216, 220, 216] -> Actual [216, 220, 216]
✅ PASS: Requested (192, 192, 192) -> Quantised [192, 192, 192] -> Actual [192, 192, 192]
✅ PASS: Requested (105, 105, 105) -> Quantised [104, 104, 104] -> Actual [104, 104, 104]
✅ PASS: Requested (169, 169, 169) -> Quantised [168, 168, 168] -> Actual [168, 168, 168]
✅ PASS: Requested (0, 0, 0) -> Quantised [0, 0, 0] -> Actual [0, 0, 0]
✅ PASS: Requested (100, 149, 237) -> Quantised [96, 148, 232] -> Actual [96, 148, 232]
✅ PASS: Requested (70, 130, 180) -> Quantised [64, 128, 176] -> Actual [64, 128, 176]
✅ PASS: Requested (0, 0, 205) -> Quantised [0, 0, 200] -> Actual [0, 0, 200]
✅ PASS: Requested (25, 25, 112) -> Quantised [24, 24, 112] -> Actual [24, 24, 112]
✅ PASS: Requested (0, 0, 139) -> Quantised [0, 0, 136] -> Actual [0, 0, 136]
✅ PASS: Requested (0, 191, 255) -> Quantised [0, 188, 248] -> Actual [0, 188, 248]
✅ PASS: Requested (30, 144, 255) -> Quantised [24, 144, 248] -> Actual [24, 144, 248]
✅ PASS: Requested (135, 206, 250) -> Quantised [128, 204, 248] -> Actual [128, 204, 248]
✅ PASS: Requested (0, 255, 255) -> Quantised [0, 252, 248] -> Actual [0, 252, 248]
✅ PASS: Requested (64, 224, 208) -> Quantised [64, 224, 208] -> Actual [64, 224, 208]
✅ PASS: Requested (0, 128, 128) -> Quantised [0, 128, 128] -> Actual [0, 128, 128]
✅ PASS: Requested (143, 188, 143) -> Quantised [136, 188, 136] -> Actual [136, 188, 136]
✅ PASS: Requested (60, 179, 113) -> Quantised [56, 176, 112] -> Actual [56, 176, 112]
✅ PASS: Requested (46, 139, 87) -> Quantised [40, 136, 80] -> Actual [40, 136, 80]
✅ PASS: Requested (0, 255, 127) -> Quantised [0, 252, 120] -> Actual [0, 252, 120]
✅ PASS: Requested (34, 139, 34) -> Quantised [32, 136, 32] -> Actual [32, 136, 32]
✅ PASS: Requested (50, 205, 50) -> Quantised [48, 204, 48] -> Actual [48, 204, 48]
✅ PASS: Requested (154, 205, 50) -> Quantised [152, 204, 48] -> Actual [152, 204, 48]
✅ PASS: Requested (128, 128, 0) -> Quantised [128, 128, 0] -> Actual [128, 128, 0]
✅ PASS: Requested (85, 107, 47) -> Quantised [80, 104, 40] -> Actual [80, 104, 40]
✅ PASS: Requested (240, 230, 140) -> Quantised [240, 228, 136] -> Actual [240, 228, 136]
✅ PASS: Requested (255, 255, 0) -> Quantised [248, 252, 0] -> Actual [248, 252, 0]
✅ PASS: Requested (255, 215, 0) -> Quantised [248, 212, 0] -> Actual [248, 212, 0]
✅ PASS: Requested (184, 134, 11) -> Quantised [184, 132, 8] -> Actual [184, 132, 8]
✅ PASS: Requested (139, 69, 19) -> Quantised [136, 68, 16] -> Actual [136, 68, 16]
✅ PASS: Requested (210, 105, 30) -> Quantised [208, 104, 24] -> Actual [208, 104, 24]
✅ PASS: Requested (255, 140, 0) -> Quantised [248, 140, 0] -> Actual [248, 140, 0]
✅ PASS: Requested (255, 69, 0) -> Quantised [248, 68, 0] -> Actual [248, 68, 0]
✅ PASS: Requested (178, 34, 34) -> Quantised [176, 32, 32] -> Actual [176, 32, 32]
✅ PASS: Requested (255, 0, 0) -> Quantised [248, 0, 0] -> Actual [248, 0, 0]
✅ PASS: Requested (220, 20, 60) -> Quantised [216, 20, 56] -> Actual [216, 20, 56]
✅ PASS: Requested (255, 192, 203) -> Quantised [248, 192, 200] -> Actual [248, 192, 200]
✅ PASS: Requested (255, 105, 180) -> Quantised [248, 104, 176] -> Actual [248, 104, 176]
✅ PASS: Requested (255, 20, 147) -> Quantised [248, 20, 144] -> Actual [248, 20, 144]
✅ PASS: Requested (199, 21, 133) -> Quantised [192, 20, 128] -> Actual [192, 20, 128]
✅ PASS: Requested (153, 50, 204) -> Quantised [152, 48, 200] -> Actual [152, 48, 200]
✅ PASS: Requested (148, 0, 211) -> Quantised [144, 0, 208] -> Actual [144, 0, 208]
✅ PASS: Requested (138, 43, 226) -> Quantised [136, 40, 224] -> Actual [136, 40, 224]
✅ PASS: Requested (75, 0, 130) -> Quantised [72, 0, 128] -> Actual [72, 0, 128]
```

## After

Tested on
https://staging-editor-static.raspberrypi.org/branches/1345_merge/web-component.html

<img width="488" height="481" alt="image"
src="https://github.com/user-attachments/assets/1c0bff80-f78c-42d1-a6bc-7c50d03e8486"
/>

```
Colours using sense.clear()
✅ PASS: Requested (255, 255, 255) -> Quantised [248, 252, 248] -> Actual [248, 252, 248]
✅ PASS: Requested (255, 0, 0) -> Quantised [248, 0, 0] -> Actual [248, 0, 0]
✅ PASS: Requested (0, 255, 0) -> Quantised [0, 252, 0] -> Actual [0, 252, 0]
✅ PASS: Requested (0, 0, 255) -> Quantised [0, 0, 248] -> Actual [0, 0, 248]
✅ PASS: Requested (245, 245, 245) -> Quantised [240, 244, 240] -> Actual [240, 244, 240]
✅ PASS: Requested (220, 220, 220) -> Quantised [216, 220, 216] -> Actual [216, 220, 216]
✅ PASS: Requested (192, 192, 192) -> Quantised [192, 192, 192] -> Actual [192, 192, 192]
✅ PASS: Requested (105, 105, 105) -> Quantised [104, 104, 104] -> Actual [104, 104, 104]
✅ PASS: Requested (169, 169, 169) -> Quantised [168, 168, 168] -> Actual [168, 168, 168]
✅ PASS: Requested (0, 0, 0) -> Quantised [0, 0, 0] -> Actual [0, 0, 0]
✅ PASS: Requested (100, 149, 237) -> Quantised [96, 148, 232] -> Actual [96, 148, 232]
✅ PASS: Requested (70, 130, 180) -> Quantised [64, 128, 176] -> Actual [64, 128, 176]
✅ PASS: Requested (0, 0, 205) -> Quantised [0, 0, 200] -> Actual [0, 0, 200]
✅ PASS: Requested (25, 25, 112) -> Quantised [24, 24, 112] -> Actual [24, 24, 112]
✅ PASS: Requested (0, 0, 139) -> Quantised [0, 0, 136] -> Actual [0, 0, 136]
✅ PASS: Requested (0, 191, 255) -> Quantised [0, 188, 248] -> Actual [0, 188, 248]
✅ PASS: Requested (30, 144, 255) -> Quantised [24, 144, 248] -> Actual [24, 144, 248]
✅ PASS: Requested (135, 206, 250) -> Quantised [128, 204, 248] -> Actual [128, 204, 248]
✅ PASS: Requested (0, 255, 255) -> Quantised [0, 252, 248] -> Actual [0, 252, 248]
✅ PASS: Requested (64, 224, 208) -> Quantised [64, 224, 208] -> Actual [64, 224, 208]
✅ PASS: Requested (0, 128, 128) -> Quantised [0, 128, 128] -> Actual [0, 128, 128]
✅ PASS: Requested (143, 188, 143) -> Quantised [136, 188, 136] -> Actual [136, 188, 136]
✅ PASS: Requested (60, 179, 113) -> Quantised [56, 176, 112] -> Actual [56, 176, 112]
✅ PASS: Requested (46, 139, 87) -> Quantised [40, 136, 80] -> Actual [40, 136, 80]
✅ PASS: Requested (0, 255, 127) -> Quantised [0, 252, 120] -> Actual [0, 252, 120]
✅ PASS: Requested (34, 139, 34) -> Quantised [32, 136, 32] -> Actual [32, 136, 32]
✅ PASS: Requested (50, 205, 50) -> Quantised [48, 204, 48] -> Actual [48, 204, 48]
✅ PASS: Requested (154, 205, 50) -> Quantised [152, 204, 48] -> Actual [152, 204, 48]
✅ PASS: Requested (128, 128, 0) -> Quantised [128, 128, 0] -> Actual [128, 128, 0]
✅ PASS: Requested (85, 107, 47) -> Quantised [80, 104, 40] -> Actual [80, 104, 40]
✅ PASS: Requested (240, 230, 140) -> Quantised [240, 228, 136] -> Actual [240, 228, 136]
✅ PASS: Requested (255, 255, 0) -> Quantised [248, 252, 0] -> Actual [248, 252, 0]
✅ PASS: Requested (255, 215, 0) -> Quantised [248, 212, 0] -> Actual [248, 212, 0]
✅ PASS: Requested (184, 134, 11) -> Quantised [184, 132, 8] -> Actual [184, 132, 8]
✅ PASS: Requested (139, 69, 19) -> Quantised [136, 68, 16] -> Actual [136, 68, 16]
✅ PASS: Requested (210, 105, 30) -> Quantised [208, 104, 24] -> Actual [208, 104, 24]
✅ PASS: Requested (255, 140, 0) -> Quantised [248, 140, 0] -> Actual [248, 140, 0]
✅ PASS: Requested (255, 69, 0) -> Quantised [248, 68, 0] -> Actual [248, 68, 0]
✅ PASS: Requested (178, 34, 34) -> Quantised [176, 32, 32] -> Actual [176, 32, 32]
✅ PASS: Requested (255, 0, 0) -> Quantised [248, 0, 0] -> Actual [248, 0, 0]
✅ PASS: Requested (220, 20, 60) -> Quantised [216, 20, 56] -> Actual [216, 20, 56]
✅ PASS: Requested (255, 192, 203) -> Quantised [248, 192, 200] -> Actual [248, 192, 200]
✅ PASS: Requested (255, 105, 180) -> Quantised [248, 104, 176] -> Actual [248, 104, 176]
✅ PASS: Requested (255, 20, 147) -> Quantised [248, 20, 144] -> Actual [248, 20, 144]
✅ PASS: Requested (199, 21, 133) -> Quantised [192, 20, 128] -> Actual [192, 20, 128]
✅ PASS: Requested (153, 50, 204) -> Quantised [152, 48, 200] -> Actual [152, 48, 200]
✅ PASS: Requested (148, 0, 211) -> Quantised [144, 0, 208] -> Actual [144, 0, 208]
✅ PASS: Requested (138, 43, 226) -> Quantised [136, 40, 224] -> Actual [136, 40, 224]
✅ PASS: Requested (75, 0, 130) -> Quantised [72, 0, 128] -> Actual [72, 0, 128]
Colours using sense.set_pixel()
✅ PASS: Requested (255, 255, 255) -> Quantised [248, 252, 248] -> Actual [248, 252, 248]
✅ PASS: Requested (255, 0, 0) -> Quantised [248, 0, 0] -> Actual [248, 0, 0]
✅ PASS: Requested (0, 255, 0) -> Quantised [0, 252, 0] -> Actual [0, 252, 0]
✅ PASS: Requested (0, 0, 255) -> Quantised [0, 0, 248] -> Actual [0, 0, 248]
✅ PASS: Requested (245, 245, 245) -> Quantised [240, 244, 240] -> Actual [240, 244, 240]
✅ PASS: Requested (220, 220, 220) -> Quantised [216, 220, 216] -> Actual [216, 220, 216]
✅ PASS: Requested (192, 192, 192) -> Quantised [192, 192, 192] -> Actual [192, 192, 192]
✅ PASS: Requested (105, 105, 105) -> Quantised [104, 104, 104] -> Actual [104, 104, 104]
✅ PASS: Requested (169, 169, 169) -> Quantised [168, 168, 168] -> Actual [168, 168, 168]
✅ PASS: Requested (0, 0, 0) -> Quantised [0, 0, 0] -> Actual [0, 0, 0]
✅ PASS: Requested (100, 149, 237) -> Quantised [96, 148, 232] -> Actual [96, 148, 232]
✅ PASS: Requested (70, 130, 180) -> Quantised [64, 128, 176] -> Actual [64, 128, 176]
✅ PASS: Requested (0, 0, 205) -> Quantised [0, 0, 200] -> Actual [0, 0, 200]
✅ PASS: Requested (25, 25, 112) -> Quantised [24, 24, 112] -> Actual [24, 24, 112]
✅ PASS: Requested (0, 0, 139) -> Quantised [0, 0, 136] -> Actual [0, 0, 136]
✅ PASS: Requested (0, 191, 255) -> Quantised [0, 188, 248] -> Actual [0, 188, 248]
✅ PASS: Requested (30, 144, 255) -> Quantised [24, 144, 248] -> Actual [24, 144, 248]
✅ PASS: Requested (135, 206, 250) -> Quantised [128, 204, 248] -> Actual [128, 204, 248]
✅ PASS: Requested (0, 255, 255) -> Quantised [0, 252, 248] -> Actual [0, 252, 248]
✅ PASS: Requested (64, 224, 208) -> Quantised [64, 224, 208] -> Actual [64, 224, 208]
✅ PASS: Requested (0, 128, 128) -> Quantised [0, 128, 128] -> Actual [0, 128, 128]
✅ PASS: Requested (143, 188, 143) -> Quantised [136, 188, 136] -> Actual [136, 188, 136]
✅ PASS: Requested (60, 179, 113) -> Quantised [56, 176, 112] -> Actual [56, 176, 112]
✅ PASS: Requested (46, 139, 87) -> Quantised [40, 136, 80] -> Actual [40, 136, 80]
✅ PASS: Requested (0, 255, 127) -> Quantised [0, 252, 120] -> Actual [0, 252, 120]
✅ PASS: Requested (34, 139, 34) -> Quantised [32, 136, 32] -> Actual [32, 136, 32]
✅ PASS: Requested (50, 205, 50) -> Quantised [48, 204, 48] -> Actual [48, 204, 48]
✅ PASS: Requested (154, 205, 50) -> Quantised [152, 204, 48] -> Actual [152, 204, 48]
✅ PASS: Requested (128, 128, 0) -> Quantised [128, 128, 0] -> Actual [128, 128, 0]
✅ PASS: Requested (85, 107, 47) -> Quantised [80, 104, 40] -> Actual [80, 104, 40]
✅ PASS: Requested (240, 230, 140) -> Quantised [240, 228, 136] -> Actual [240, 228, 136]
✅ PASS: Requested (255, 255, 0) -> Quantised [248, 252, 0] -> Actual [248, 252, 0]
✅ PASS: Requested (255, 215, 0) -> Quantised [248, 212, 0] -> Actual [248, 212, 0]
✅ PASS: Requested (184, 134, 11) -> Quantised [184, 132, 8] -> Actual [184, 132, 8]
✅ PASS: Requested (139, 69, 19) -> Quantised [136, 68, 16] -> Actual [136, 68, 16]
✅ PASS: Requested (210, 105, 30) -> Quantised [208, 104, 24] -> Actual [208, 104, 24]
✅ PASS: Requested (255, 140, 0) -> Quantised [248, 140, 0] -> Actual [248, 140, 0]
✅ PASS: Requested (255, 69, 0) -> Quantised [248, 68, 0] -> Actual [248, 68, 0]
✅ PASS: Requested (178, 34, 34) -> Quantised [176, 32, 32] -> Actual [176, 32, 32]
✅ PASS: Requested (255, 0, 0) -> Quantised [248, 0, 0] -> Actual [248, 0, 0]
✅ PASS: Requested (220, 20, 60) -> Quantised [216, 20, 56] -> Actual [216, 20, 56]
✅ PASS: Requested (255, 192, 203) -> Quantised [248, 192, 200] -> Actual [248, 192, 200]
✅ PASS: Requested (255, 105, 180) -> Quantised [248, 104, 176] -> Actual [248, 104, 176]
✅ PASS: Requested (255, 20, 147) -> Quantised [248, 20, 144] -> Actual [248, 20, 144]
✅ PASS: Requested (199, 21, 133) -> Quantised [192, 20, 128] -> Actual [192, 20, 128]
✅ PASS: Requested (153, 50, 204) -> Quantised [152, 48, 200] -> Actual [152, 48, 200]
✅ PASS: Requested (148, 0, 211) -> Quantised [144, 0, 208] -> Actual [144, 0, 208]
✅ PASS: Requested (138, 43, 226) -> Quantised [136, 40, 224] -> Actual [136, 40, 224]
✅ PASS: Requested (75, 0, 130) -> Quantised [72, 0, 128] -> Actual [72, 0, 128]
```
jamiebenstead pushed a commit that referenced this pull request Mar 3, 2026
In #1247 we added code to ensure that 24-bit colour was being converted
to RGB565 (16 bit). It turns out that in the Flight Case model this was
already happening. The code was then *erroneously* multiplying the
colour values by 255. Also `set_pixels` was not quantising colours
before setting.

This PR adds in a function that is called by both `set_pixel` and
`set_pixels` to quantise the colours before setting, and updating the
internal representation of what the display contains (the
`Sk.sense_hat.pixels` array) such that `get_pixel` and `get_pixels`
return the correctly quantised colours (rather than the ones requested),
as described in the [Sense Hat library API
docs](https://pythonhosted.org/sense-hat/api/#get_pixels).

## Sample code

This code flashes through the colours on the display, and then reads
using `get_pixel` to make sure the colour set is correctly quantised. In
the console there will be a list of ✅ and ❌ marks for colours as they
pass/fail.

NB I think there is a race somewhere as the first colour (white) seems
to often fail the first run through. All the rest seem fine though 🤷🏻

```python
# Import the libraries
from sense_hat import SenseHat
from time import sleep

# Set up the Sense HAT
sense = SenseHat()
sense.set_rotation(270, False)

# --- Quantisation helper to match set_pixel ---
def check_quantise_rgb(x, y, requested):
    actual = sense.get_pixel(x, y)

    expected = [0,0,0]
    expected[0] = (requested[0] >> 3) << 3
    expected[1] = (requested[1] >> 2) << 2
    expected[2] = (requested[2] >> 3) << 3

    if actual == expected:
        print(f"✅ PASS: Requested {requested} -> Quantised {expected} -> Actual {actual}")
    else:
        print(f"❌ FAIL: Requested {requested} -> Quantised {expected} -> Actual {actual}")

colours = [
    (255, 255, 255),  # White
    (255, 0, 0),      # Red
    (0, 255, 0),      # Green
    (0, 0, 255),      # Blue
    (245, 245, 245),  # WhiteSmoke
    (220, 220, 220),  # Gainsboro
    (192, 192, 192),  # Silver
    (105, 105, 105),  # DimGray
    (169, 169, 169),  # DarkGray
    (0, 0, 0),        # Black
    (100, 149, 237),  # CornflowerBlue
    (70, 130, 180),   # SteelBlue
    (0, 0, 205),      # MediumBlue
    (25, 25, 112),    # MidnightBlue
    (0, 0, 139),      # DarkBlue
    (0, 191, 255),    # DeepSkyBlue
    (30, 144, 255),   # DodgerBlue
    (135, 206, 250),  # LightSkyBlue
    (0, 255, 255),    # Cyan
    (64, 224, 208),   # Turquoise
    (0, 128, 128),    # Teal
    (143, 188, 143),  # DarkSeaGreen
    (60, 179, 113),   # MediumSeaGreen
    (46, 139, 87),    # SeaGreen
    (0, 255, 127),    # SpringGreen
    (34, 139, 34),    # ForestGreen
    (50, 205, 50),    # LimeGreen
    (154, 205, 50),   # YellowGreen
    (128, 128, 0),    # Olive
    (85, 107, 47),    # DarkOliveGreen
    (240, 230, 140),  # Khaki
    (255, 255, 0),    # Yellow
    (255, 215, 0),    # Gold
    (184, 134, 11),   # DarkGoldenrod
    (139, 69, 19),    # SaddleBrown
    (210, 105, 30),   # Chocolate
    (255, 140, 0),    # DarkOrange
    (255, 69, 0),     # OrangeRed
    (178, 34, 34),    # Firebrick
    (255, 0, 0),      # Red
    (220, 20, 60),    # Crimson
    (255, 192, 203),  # Pink
    (255, 105, 180),  # HotPink
    (255, 20, 147),   # DeepPink
    (199, 21, 133),   # MediumVioletRed
    (153, 50, 204),   # DarkOrchid
    (148, 0, 211),    # DarkViolet
    (138, 43, 226),   # BlueViolet
    (75, 0, 130),     # Indigo
]

# First demo: sense.clear
print('Colours using sense.clear()')
sense.show_message("sense.clear", scroll_speed=0.005)
for colour in colours:
    sense.clear(colour)
    check_quantise_rgb(0,0,colour)
    sleep(0.1)

# Second demo: sense.set_pixel
print('Colours using sense.set_pixel()')
sense.clear()
sense.show_message("sense.set_pixel", scroll_speed=0.005)
x, y = [0, 0]
for colour in colours:
    sense.set_pixel(x, y, colour)
    check_quantise_rgb(x,y,colour)
    x += 1
    if x > 7:
        y += 1
        x = 0
```

## Before

Tried on
https://staging-editor-static.raspberrypi.org/branches/main/web-component.html

<img width="442" height="421" alt="image"
src="https://github.com/user-attachments/assets/ce5c98f4-7d91-4dfe-a98a-c5b13c51ff5b"
/>

Text output

```
Colours using sense.clear()
❌ FAIL: Requested (255, 255, 255) -> Quantised [248, 252, 248] -> Actual [255, 255, 255]
❌ FAIL: Requested (255, 0, 0) -> Quantised [248, 0, 0] -> Actual [255, 0, 0]
❌ FAIL: Requested (0, 255, 0) -> Quantised [0, 252, 0] -> Actual [0, 255, 0]
❌ FAIL: Requested (0, 0, 255) -> Quantised [0, 0, 248] -> Actual [0, 0, 255]
❌ FAIL: Requested (245, 245, 245) -> Quantised [240, 244, 240] -> Actual [245, 245, 245]
❌ FAIL: Requested (220, 220, 220) -> Quantised [216, 220, 216] -> Actual [220, 220, 220]
✅ PASS: Requested (192, 192, 192) -> Quantised [192, 192, 192] -> Actual [192, 192, 192]
❌ FAIL: Requested (105, 105, 105) -> Quantised [104, 104, 104] -> Actual [105, 105, 105]
❌ FAIL: Requested (169, 169, 169) -> Quantised [168, 168, 168] -> Actual [169, 169, 169]
✅ PASS: Requested (0, 0, 0) -> Quantised [0, 0, 0] -> Actual [0, 0, 0]
❌ FAIL: Requested (100, 149, 237) -> Quantised [96, 148, 232] -> Actual [100, 149, 237]
❌ FAIL: Requested (70, 130, 180) -> Quantised [64, 128, 176] -> Actual [70, 130, 180]
❌ FAIL: Requested (0, 0, 205) -> Quantised [0, 0, 200] -> Actual [0, 0, 205]
❌ FAIL: Requested (25, 25, 112) -> Quantised [24, 24, 112] -> Actual [25, 25, 112]
❌ FAIL: Requested (0, 0, 139) -> Quantised [0, 0, 136] -> Actual [0, 0, 139]
❌ FAIL: Requested (0, 191, 255) -> Quantised [0, 188, 248] -> Actual [0, 191, 255]
❌ FAIL: Requested (30, 144, 255) -> Quantised [24, 144, 248] -> Actual [30, 144, 255]
❌ FAIL: Requested (135, 206, 250) -> Quantised [128, 204, 248] -> Actual [135, 206, 250]
❌ FAIL: Requested (0, 255, 255) -> Quantised [0, 252, 248] -> Actual [0, 255, 255]
✅ PASS: Requested (64, 224, 208) -> Quantised [64, 224, 208] -> Actual [64, 224, 208]
✅ PASS: Requested (0, 128, 128) -> Quantised [0, 128, 128] -> Actual [0, 128, 128]
❌ FAIL: Requested (143, 188, 143) -> Quantised [136, 188, 136] -> Actual [143, 188, 143]
❌ FAIL: Requested (60, 179, 113) -> Quantised [56, 176, 112] -> Actual [60, 179, 113]
❌ FAIL: Requested (46, 139, 87) -> Quantised [40, 136, 80] -> Actual [46, 139, 87]
❌ FAIL: Requested (0, 255, 127) -> Quantised [0, 252, 120] -> Actual [0, 255, 127]
❌ FAIL: Requested (34, 139, 34) -> Quantised [32, 136, 32] -> Actual [34, 139, 34]
❌ FAIL: Requested (50, 205, 50) -> Quantised [48, 204, 48] -> Actual [50, 205, 50]
❌ FAIL: Requested (154, 205, 50) -> Quantised [152, 204, 48] -> Actual [154, 205, 50]
✅ PASS: Requested (128, 128, 0) -> Quantised [128, 128, 0] -> Actual [128, 128, 0]
❌ FAIL: Requested (85, 107, 47) -> Quantised [80, 104, 40] -> Actual [85, 107, 47]
❌ FAIL: Requested (240, 230, 140) -> Quantised [240, 228, 136] -> Actual [240, 230, 140]
❌ FAIL: Requested (255, 255, 0) -> Quantised [248, 252, 0] -> Actual [255, 255, 0]
❌ FAIL: Requested (255, 215, 0) -> Quantised [248, 212, 0] -> Actual [255, 215, 0]
❌ FAIL: Requested (184, 134, 11) -> Quantised [184, 132, 8] -> Actual [184, 134, 11]
❌ FAIL: Requested (139, 69, 19) -> Quantised [136, 68, 16] -> Actual [139, 69, 19]
❌ FAIL: Requested (210, 105, 30) -> Quantised [208, 104, 24] -> Actual [210, 105, 30]
❌ FAIL: Requested (255, 140, 0) -> Quantised [248, 140, 0] -> Actual [255, 140, 0]
❌ FAIL: Requested (255, 69, 0) -> Quantised [248, 68, 0] -> Actual [255, 69, 0]
❌ FAIL: Requested (178, 34, 34) -> Quantised [176, 32, 32] -> Actual [178, 34, 34]
❌ FAIL: Requested (255, 0, 0) -> Quantised [248, 0, 0] -> Actual [255, 0, 0]
❌ FAIL: Requested (220, 20, 60) -> Quantised [216, 20, 56] -> Actual [220, 20, 60]
❌ FAIL: Requested (255, 192, 203) -> Quantised [248, 192, 200] -> Actual [255, 192, 203]
❌ FAIL: Requested (255, 105, 180) -> Quantised [248, 104, 176] -> Actual [255, 105, 180]
❌ FAIL: Requested (255, 20, 147) -> Quantised [248, 20, 144] -> Actual [255, 20, 147]
❌ FAIL: Requested (199, 21, 133) -> Quantised [192, 20, 128] -> Actual [199, 21, 133]
❌ FAIL: Requested (153, 50, 204) -> Quantised [152, 48, 200] -> Actual [153, 50, 204]
❌ FAIL: Requested (148, 0, 211) -> Quantised [144, 0, 208] -> Actual [148, 0, 211]
❌ FAIL: Requested (138, 43, 226) -> Quantised [136, 40, 224] -> Actual [138, 43, 226]
❌ FAIL: Requested (75, 0, 130) -> Quantised [72, 0, 128] -> Actual [75, 0, 130]
Colours using sense.set_pixel()
✅ PASS: Requested (255, 255, 255) -> Quantised [248, 252, 248] -> Actual [248, 252, 248]
✅ PASS: Requested (255, 0, 0) -> Quantised [248, 0, 0] -> Actual [248, 0, 0]
✅ PASS: Requested (0, 255, 0) -> Quantised [0, 252, 0] -> Actual [0, 252, 0]
✅ PASS: Requested (0, 0, 255) -> Quantised [0, 0, 248] -> Actual [0, 0, 248]
✅ PASS: Requested (245, 245, 245) -> Quantised [240, 244, 240] -> Actual [240, 244, 240]
✅ PASS: Requested (220, 220, 220) -> Quantised [216, 220, 216] -> Actual [216, 220, 216]
✅ PASS: Requested (192, 192, 192) -> Quantised [192, 192, 192] -> Actual [192, 192, 192]
✅ PASS: Requested (105, 105, 105) -> Quantised [104, 104, 104] -> Actual [104, 104, 104]
✅ PASS: Requested (169, 169, 169) -> Quantised [168, 168, 168] -> Actual [168, 168, 168]
✅ PASS: Requested (0, 0, 0) -> Quantised [0, 0, 0] -> Actual [0, 0, 0]
✅ PASS: Requested (100, 149, 237) -> Quantised [96, 148, 232] -> Actual [96, 148, 232]
✅ PASS: Requested (70, 130, 180) -> Quantised [64, 128, 176] -> Actual [64, 128, 176]
✅ PASS: Requested (0, 0, 205) -> Quantised [0, 0, 200] -> Actual [0, 0, 200]
✅ PASS: Requested (25, 25, 112) -> Quantised [24, 24, 112] -> Actual [24, 24, 112]
✅ PASS: Requested (0, 0, 139) -> Quantised [0, 0, 136] -> Actual [0, 0, 136]
✅ PASS: Requested (0, 191, 255) -> Quantised [0, 188, 248] -> Actual [0, 188, 248]
✅ PASS: Requested (30, 144, 255) -> Quantised [24, 144, 248] -> Actual [24, 144, 248]
✅ PASS: Requested (135, 206, 250) -> Quantised [128, 204, 248] -> Actual [128, 204, 248]
✅ PASS: Requested (0, 255, 255) -> Quantised [0, 252, 248] -> Actual [0, 252, 248]
✅ PASS: Requested (64, 224, 208) -> Quantised [64, 224, 208] -> Actual [64, 224, 208]
✅ PASS: Requested (0, 128, 128) -> Quantised [0, 128, 128] -> Actual [0, 128, 128]
✅ PASS: Requested (143, 188, 143) -> Quantised [136, 188, 136] -> Actual [136, 188, 136]
✅ PASS: Requested (60, 179, 113) -> Quantised [56, 176, 112] -> Actual [56, 176, 112]
✅ PASS: Requested (46, 139, 87) -> Quantised [40, 136, 80] -> Actual [40, 136, 80]
✅ PASS: Requested (0, 255, 127) -> Quantised [0, 252, 120] -> Actual [0, 252, 120]
✅ PASS: Requested (34, 139, 34) -> Quantised [32, 136, 32] -> Actual [32, 136, 32]
✅ PASS: Requested (50, 205, 50) -> Quantised [48, 204, 48] -> Actual [48, 204, 48]
✅ PASS: Requested (154, 205, 50) -> Quantised [152, 204, 48] -> Actual [152, 204, 48]
✅ PASS: Requested (128, 128, 0) -> Quantised [128, 128, 0] -> Actual [128, 128, 0]
✅ PASS: Requested (85, 107, 47) -> Quantised [80, 104, 40] -> Actual [80, 104, 40]
✅ PASS: Requested (240, 230, 140) -> Quantised [240, 228, 136] -> Actual [240, 228, 136]
✅ PASS: Requested (255, 255, 0) -> Quantised [248, 252, 0] -> Actual [248, 252, 0]
✅ PASS: Requested (255, 215, 0) -> Quantised [248, 212, 0] -> Actual [248, 212, 0]
✅ PASS: Requested (184, 134, 11) -> Quantised [184, 132, 8] -> Actual [184, 132, 8]
✅ PASS: Requested (139, 69, 19) -> Quantised [136, 68, 16] -> Actual [136, 68, 16]
✅ PASS: Requested (210, 105, 30) -> Quantised [208, 104, 24] -> Actual [208, 104, 24]
✅ PASS: Requested (255, 140, 0) -> Quantised [248, 140, 0] -> Actual [248, 140, 0]
✅ PASS: Requested (255, 69, 0) -> Quantised [248, 68, 0] -> Actual [248, 68, 0]
✅ PASS: Requested (178, 34, 34) -> Quantised [176, 32, 32] -> Actual [176, 32, 32]
✅ PASS: Requested (255, 0, 0) -> Quantised [248, 0, 0] -> Actual [248, 0, 0]
✅ PASS: Requested (220, 20, 60) -> Quantised [216, 20, 56] -> Actual [216, 20, 56]
✅ PASS: Requested (255, 192, 203) -> Quantised [248, 192, 200] -> Actual [248, 192, 200]
✅ PASS: Requested (255, 105, 180) -> Quantised [248, 104, 176] -> Actual [248, 104, 176]
✅ PASS: Requested (255, 20, 147) -> Quantised [248, 20, 144] -> Actual [248, 20, 144]
✅ PASS: Requested (199, 21, 133) -> Quantised [192, 20, 128] -> Actual [192, 20, 128]
✅ PASS: Requested (153, 50, 204) -> Quantised [152, 48, 200] -> Actual [152, 48, 200]
✅ PASS: Requested (148, 0, 211) -> Quantised [144, 0, 208] -> Actual [144, 0, 208]
✅ PASS: Requested (138, 43, 226) -> Quantised [136, 40, 224] -> Actual [136, 40, 224]
✅ PASS: Requested (75, 0, 130) -> Quantised [72, 0, 128] -> Actual [72, 0, 128]
```

## After

Tested on
https://staging-editor-static.raspberrypi.org/branches/1345_merge/web-component.html

<img width="488" height="481" alt="image"
src="https://github.com/user-attachments/assets/1c0bff80-f78c-42d1-a6bc-7c50d03e8486"
/>

```
Colours using sense.clear()
✅ PASS: Requested (255, 255, 255) -> Quantised [248, 252, 248] -> Actual [248, 252, 248]
✅ PASS: Requested (255, 0, 0) -> Quantised [248, 0, 0] -> Actual [248, 0, 0]
✅ PASS: Requested (0, 255, 0) -> Quantised [0, 252, 0] -> Actual [0, 252, 0]
✅ PASS: Requested (0, 0, 255) -> Quantised [0, 0, 248] -> Actual [0, 0, 248]
✅ PASS: Requested (245, 245, 245) -> Quantised [240, 244, 240] -> Actual [240, 244, 240]
✅ PASS: Requested (220, 220, 220) -> Quantised [216, 220, 216] -> Actual [216, 220, 216]
✅ PASS: Requested (192, 192, 192) -> Quantised [192, 192, 192] -> Actual [192, 192, 192]
✅ PASS: Requested (105, 105, 105) -> Quantised [104, 104, 104] -> Actual [104, 104, 104]
✅ PASS: Requested (169, 169, 169) -> Quantised [168, 168, 168] -> Actual [168, 168, 168]
✅ PASS: Requested (0, 0, 0) -> Quantised [0, 0, 0] -> Actual [0, 0, 0]
✅ PASS: Requested (100, 149, 237) -> Quantised [96, 148, 232] -> Actual [96, 148, 232]
✅ PASS: Requested (70, 130, 180) -> Quantised [64, 128, 176] -> Actual [64, 128, 176]
✅ PASS: Requested (0, 0, 205) -> Quantised [0, 0, 200] -> Actual [0, 0, 200]
✅ PASS: Requested (25, 25, 112) -> Quantised [24, 24, 112] -> Actual [24, 24, 112]
✅ PASS: Requested (0, 0, 139) -> Quantised [0, 0, 136] -> Actual [0, 0, 136]
✅ PASS: Requested (0, 191, 255) -> Quantised [0, 188, 248] -> Actual [0, 188, 248]
✅ PASS: Requested (30, 144, 255) -> Quantised [24, 144, 248] -> Actual [24, 144, 248]
✅ PASS: Requested (135, 206, 250) -> Quantised [128, 204, 248] -> Actual [128, 204, 248]
✅ PASS: Requested (0, 255, 255) -> Quantised [0, 252, 248] -> Actual [0, 252, 248]
✅ PASS: Requested (64, 224, 208) -> Quantised [64, 224, 208] -> Actual [64, 224, 208]
✅ PASS: Requested (0, 128, 128) -> Quantised [0, 128, 128] -> Actual [0, 128, 128]
✅ PASS: Requested (143, 188, 143) -> Quantised [136, 188, 136] -> Actual [136, 188, 136]
✅ PASS: Requested (60, 179, 113) -> Quantised [56, 176, 112] -> Actual [56, 176, 112]
✅ PASS: Requested (46, 139, 87) -> Quantised [40, 136, 80] -> Actual [40, 136, 80]
✅ PASS: Requested (0, 255, 127) -> Quantised [0, 252, 120] -> Actual [0, 252, 120]
✅ PASS: Requested (34, 139, 34) -> Quantised [32, 136, 32] -> Actual [32, 136, 32]
✅ PASS: Requested (50, 205, 50) -> Quantised [48, 204, 48] -> Actual [48, 204, 48]
✅ PASS: Requested (154, 205, 50) -> Quantised [152, 204, 48] -> Actual [152, 204, 48]
✅ PASS: Requested (128, 128, 0) -> Quantised [128, 128, 0] -> Actual [128, 128, 0]
✅ PASS: Requested (85, 107, 47) -> Quantised [80, 104, 40] -> Actual [80, 104, 40]
✅ PASS: Requested (240, 230, 140) -> Quantised [240, 228, 136] -> Actual [240, 228, 136]
✅ PASS: Requested (255, 255, 0) -> Quantised [248, 252, 0] -> Actual [248, 252, 0]
✅ PASS: Requested (255, 215, 0) -> Quantised [248, 212, 0] -> Actual [248, 212, 0]
✅ PASS: Requested (184, 134, 11) -> Quantised [184, 132, 8] -> Actual [184, 132, 8]
✅ PASS: Requested (139, 69, 19) -> Quantised [136, 68, 16] -> Actual [136, 68, 16]
✅ PASS: Requested (210, 105, 30) -> Quantised [208, 104, 24] -> Actual [208, 104, 24]
✅ PASS: Requested (255, 140, 0) -> Quantised [248, 140, 0] -> Actual [248, 140, 0]
✅ PASS: Requested (255, 69, 0) -> Quantised [248, 68, 0] -> Actual [248, 68, 0]
✅ PASS: Requested (178, 34, 34) -> Quantised [176, 32, 32] -> Actual [176, 32, 32]
✅ PASS: Requested (255, 0, 0) -> Quantised [248, 0, 0] -> Actual [248, 0, 0]
✅ PASS: Requested (220, 20, 60) -> Quantised [216, 20, 56] -> Actual [216, 20, 56]
✅ PASS: Requested (255, 192, 203) -> Quantised [248, 192, 200] -> Actual [248, 192, 200]
✅ PASS: Requested (255, 105, 180) -> Quantised [248, 104, 176] -> Actual [248, 104, 176]
✅ PASS: Requested (255, 20, 147) -> Quantised [248, 20, 144] -> Actual [248, 20, 144]
✅ PASS: Requested (199, 21, 133) -> Quantised [192, 20, 128] -> Actual [192, 20, 128]
✅ PASS: Requested (153, 50, 204) -> Quantised [152, 48, 200] -> Actual [152, 48, 200]
✅ PASS: Requested (148, 0, 211) -> Quantised [144, 0, 208] -> Actual [144, 0, 208]
✅ PASS: Requested (138, 43, 226) -> Quantised [136, 40, 224] -> Actual [136, 40, 224]
✅ PASS: Requested (75, 0, 130) -> Quantised [72, 0, 128] -> Actual [72, 0, 128]
Colours using sense.set_pixel()
✅ PASS: Requested (255, 255, 255) -> Quantised [248, 252, 248] -> Actual [248, 252, 248]
✅ PASS: Requested (255, 0, 0) -> Quantised [248, 0, 0] -> Actual [248, 0, 0]
✅ PASS: Requested (0, 255, 0) -> Quantised [0, 252, 0] -> Actual [0, 252, 0]
✅ PASS: Requested (0, 0, 255) -> Quantised [0, 0, 248] -> Actual [0, 0, 248]
✅ PASS: Requested (245, 245, 245) -> Quantised [240, 244, 240] -> Actual [240, 244, 240]
✅ PASS: Requested (220, 220, 220) -> Quantised [216, 220, 216] -> Actual [216, 220, 216]
✅ PASS: Requested (192, 192, 192) -> Quantised [192, 192, 192] -> Actual [192, 192, 192]
✅ PASS: Requested (105, 105, 105) -> Quantised [104, 104, 104] -> Actual [104, 104, 104]
✅ PASS: Requested (169, 169, 169) -> Quantised [168, 168, 168] -> Actual [168, 168, 168]
✅ PASS: Requested (0, 0, 0) -> Quantised [0, 0, 0] -> Actual [0, 0, 0]
✅ PASS: Requested (100, 149, 237) -> Quantised [96, 148, 232] -> Actual [96, 148, 232]
✅ PASS: Requested (70, 130, 180) -> Quantised [64, 128, 176] -> Actual [64, 128, 176]
✅ PASS: Requested (0, 0, 205) -> Quantised [0, 0, 200] -> Actual [0, 0, 200]
✅ PASS: Requested (25, 25, 112) -> Quantised [24, 24, 112] -> Actual [24, 24, 112]
✅ PASS: Requested (0, 0, 139) -> Quantised [0, 0, 136] -> Actual [0, 0, 136]
✅ PASS: Requested (0, 191, 255) -> Quantised [0, 188, 248] -> Actual [0, 188, 248]
✅ PASS: Requested (30, 144, 255) -> Quantised [24, 144, 248] -> Actual [24, 144, 248]
✅ PASS: Requested (135, 206, 250) -> Quantised [128, 204, 248] -> Actual [128, 204, 248]
✅ PASS: Requested (0, 255, 255) -> Quantised [0, 252, 248] -> Actual [0, 252, 248]
✅ PASS: Requested (64, 224, 208) -> Quantised [64, 224, 208] -> Actual [64, 224, 208]
✅ PASS: Requested (0, 128, 128) -> Quantised [0, 128, 128] -> Actual [0, 128, 128]
✅ PASS: Requested (143, 188, 143) -> Quantised [136, 188, 136] -> Actual [136, 188, 136]
✅ PASS: Requested (60, 179, 113) -> Quantised [56, 176, 112] -> Actual [56, 176, 112]
✅ PASS: Requested (46, 139, 87) -> Quantised [40, 136, 80] -> Actual [40, 136, 80]
✅ PASS: Requested (0, 255, 127) -> Quantised [0, 252, 120] -> Actual [0, 252, 120]
✅ PASS: Requested (34, 139, 34) -> Quantised [32, 136, 32] -> Actual [32, 136, 32]
✅ PASS: Requested (50, 205, 50) -> Quantised [48, 204, 48] -> Actual [48, 204, 48]
✅ PASS: Requested (154, 205, 50) -> Quantised [152, 204, 48] -> Actual [152, 204, 48]
✅ PASS: Requested (128, 128, 0) -> Quantised [128, 128, 0] -> Actual [128, 128, 0]
✅ PASS: Requested (85, 107, 47) -> Quantised [80, 104, 40] -> Actual [80, 104, 40]
✅ PASS: Requested (240, 230, 140) -> Quantised [240, 228, 136] -> Actual [240, 228, 136]
✅ PASS: Requested (255, 255, 0) -> Quantised [248, 252, 0] -> Actual [248, 252, 0]
✅ PASS: Requested (255, 215, 0) -> Quantised [248, 212, 0] -> Actual [248, 212, 0]
✅ PASS: Requested (184, 134, 11) -> Quantised [184, 132, 8] -> Actual [184, 132, 8]
✅ PASS: Requested (139, 69, 19) -> Quantised [136, 68, 16] -> Actual [136, 68, 16]
✅ PASS: Requested (210, 105, 30) -> Quantised [208, 104, 24] -> Actual [208, 104, 24]
✅ PASS: Requested (255, 140, 0) -> Quantised [248, 140, 0] -> Actual [248, 140, 0]
✅ PASS: Requested (255, 69, 0) -> Quantised [248, 68, 0] -> Actual [248, 68, 0]
✅ PASS: Requested (178, 34, 34) -> Quantised [176, 32, 32] -> Actual [176, 32, 32]
✅ PASS: Requested (255, 0, 0) -> Quantised [248, 0, 0] -> Actual [248, 0, 0]
✅ PASS: Requested (220, 20, 60) -> Quantised [216, 20, 56] -> Actual [216, 20, 56]
✅ PASS: Requested (255, 192, 203) -> Quantised [248, 192, 200] -> Actual [248, 192, 200]
✅ PASS: Requested (255, 105, 180) -> Quantised [248, 104, 176] -> Actual [248, 104, 176]
✅ PASS: Requested (255, 20, 147) -> Quantised [248, 20, 144] -> Actual [248, 20, 144]
✅ PASS: Requested (199, 21, 133) -> Quantised [192, 20, 128] -> Actual [192, 20, 128]
✅ PASS: Requested (153, 50, 204) -> Quantised [152, 48, 200] -> Actual [152, 48, 200]
✅ PASS: Requested (148, 0, 211) -> Quantised [144, 0, 208] -> Actual [144, 0, 208]
✅ PASS: Requested (138, 43, 226) -> Quantised [136, 40, 224] -> Actual [136, 40, 224]
✅ PASS: Requested (75, 0, 130) -> Quantised [72, 0, 128] -> Actual [72, 0, 128]
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants