///|
/// Immutable pixel snapshot plus layout metadata.
///
/// This mirrors the lightweight role of Skia's `SkPixmap`, but owns the copied
/// bytes on the MoonBit side so it is safe across backend boundaries.
pub(all) struct Pixmap {
image_info : ImageInfo
row_bytes : Int
pixels : Bytes
} derive(Debug, Eq)
///|
pub fn Pixmap::new(
image_info : ImageInfo,
row_bytes : Int,
pixels : Bytes,
) -> Pixmap? {
if image_info.is_empty() || !image_info.valid_row_bytes(row_bytes) {
None
} else if pixels.length() < image_info.compute_byte_size(row_bytes) {
None
} else {
Some({ image_info, row_bytes, pixels })
}
}
///|
pub fn Pixmap::width(self : Pixmap) -> Int {
self.image_info.width()
}
///|
pub fn Pixmap::height(self : Pixmap) -> Int {
self.image_info.height()
}
///|
pub fn Pixmap::dimensions(self : Pixmap) -> ISize {
self.image_info.dimensions
}
///|
pub fn Pixmap::bounds(self : Pixmap) -> IRect {
self.image_info.bounds()
}
///|
pub fn Pixmap::color_type(self : Pixmap) -> ColorType {
self.image_info.color_type()
}
///|
pub fn Pixmap::alpha_type(self : Pixmap) -> AlphaType {
self.image_info.alpha_type()
}
///|
pub fn Pixmap::bytes_per_pixel(self : Pixmap) -> Int {
self.image_info.bytes_per_pixel()
}
///|
pub fn Pixmap::shift_per_pixel(self : Pixmap) -> Int {
self.image_info.shift_per_pixel()
}
///|
pub fn Pixmap::row_bytes(self : Pixmap) -> Int {
self.row_bytes
}
///|
pub fn Pixmap::byte_size(self : Pixmap) -> Int {
self.image_info.compute_byte_size(self.row_bytes)
}
///|
pub fn Pixmap::byte_size64(self : Pixmap) -> Int64 {
self.image_info.compute_byte_size64(self.row_bytes)
}
///|
pub fn Pixmap::is_empty(self : Pixmap) -> Bool {
self.image_info.is_empty() || self.pixels.is_empty()
}
///|
pub fn Pixmap::contains(self : Pixmap, point : IPoint) -> Bool {
self.bounds().contains_point(point)
}
///|
pub fn Pixmap::offset(self : Pixmap, point : IPoint) -> Int? {
if self.contains(point) {
Some(self.image_info.compute_offset(point, self.row_bytes))
} else {
None
}
}
///|
/// Copy the stored channel bytes for one pixel.
pub fn Pixmap::sample(self : Pixmap, point : IPoint) -> Bytes? {
match self.offset(point) {
None => None
Some(offset) => {
let bytes_per_pixel = self.bytes_per_pixel()
if bytes_per_pixel <= 0 || offset + bytes_per_pixel > self.pixels.length() {
None
} else {
let sample : Array[Byte] = Array::new(capacity=bytes_per_pixel)
for index in 0.. Bool {
match self.sample(point) {
None => false
Some(actual) => actual == sample
}
}