+ def _write_pixel(self, x: int, y: int, value: int) -> None:
+ if self._read_only:
+ raise RuntimeError("Read-only")
+
+ # Writes the color index value into a pixel position
+ # Must update the dirty area separately
+
+ # Don't write if out of area
+ if x < 0 or x >= self._bmp_width or y < 0 or y >= self._bmp_height:
+ return
+
+ # Update one pixel of data
+ row_start = y * self._stride
+ bytes_per_value = self._bits_per_value // 8
+ if bytes_per_value < 1:
+ bit_position = 32 - ((x & self._x_mask) + 1) * self._bits_per_value
+ index = row_start + (x >> self._x_shift)
+ word = self._data[index]
+ word &= ~(self._bitmask << bit_position)
+ word |= (value & self._bitmask) << bit_position
+ self._data[index] = word
+ else:
+ row = memoryview(self._data)[row_start : row_start + self._stride]
+ if bytes_per_value == 1:
+ row[x] = value
+ elif bytes_per_value == 2:
+ struct.pack_into("<H", row, x * 2, value)
+ elif bytes_per_value == 4:
+ struct.pack_into("<I", row, x * 4, value)