- self._image.putpixel((x, y), value)
- if self._dirty_area.x1 == self._dirty_area.x2:
- self._dirty_area.x1 = x
- self._dirty_area.x2 = x + 1
- self._dirty_area.y1 = y
- self._dirty_area.y2 = y + 1
+ # update the dirty region
+ self._set_dirty_area(Area(x, y, x + 1, y + 1))
+ self._write_pixel(x, y, value)
+
+ 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