#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum AssociatedImageKind {
Label,
Thumbnail,
}
#[derive(Debug, Clone, PartialEq)]
pub struct ChannelMetadata {
pub name: String,
pub color_rgb: [u8; 3],
pub exposure_ms: f64,
}
#[derive(Debug, Clone)]
pub struct KfbHeader {
format: KfbFormat,
tile_count: i32,
base_width: i32,
base_height: i32,
scan_scale: i32,
spend_time: i32,
scan_time: i64,
image_cap_res: f64,
tile_size: i32,
channel_count: usize,
pub(crate) zoom_levels: i32,
channels: Vec<ChannelMetadata>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum KfbFormat {
Brightfield,
Fluorescence,
}
#[derive(Debug, Clone)]
pub(crate) struct KfbHeaderFields {
pub format: KfbFormat,
pub tile_count: i32,
pub base_width: i32,
pub base_height: i32,
pub scan_scale: i32,
pub spend_time: i32,
pub scan_time: i64,
pub image_cap_res: f64,
pub tile_size: i32,
pub channel_count: usize,
pub zoom_levels: i32,
pub channels: Vec<ChannelMetadata>,
}
impl KfbHeader {
pub(crate) fn new(fields: KfbHeaderFields) -> Self {
debug_assert!(
fields.channels.is_empty() || fields.channels.len() == fields.channel_count,
"channels.len() ({}) must equal channel_count ({})",
fields.channels.len(),
fields.channel_count
);
Self {
format: fields.format,
tile_count: fields.tile_count,
base_width: fields.base_width,
base_height: fields.base_height,
scan_scale: fields.scan_scale,
spend_time: fields.spend_time,
scan_time: fields.scan_time,
image_cap_res: fields.image_cap_res,
tile_size: fields.tile_size,
channel_count: fields.channel_count,
zoom_levels: fields.zoom_levels,
channels: fields.channels,
}
}
pub fn tile_count(&self) -> i32 {
self.tile_count
}
pub(crate) fn is_fluorescence(&self) -> bool {
self.format == KfbFormat::Fluorescence
}
pub fn base_width(&self) -> i32 {
self.base_width
}
pub fn base_height(&self) -> i32 {
self.base_height
}
pub fn scan_scale(&self) -> i32 {
self.scan_scale
}
pub fn spend_time(&self) -> i32 {
self.spend_time
}
pub fn scan_time(&self) -> i64 {
self.scan_time
}
pub fn tile_size(&self) -> i32 {
self.tile_size
}
pub fn channel_count(&self) -> usize {
self.channel_count
}
pub fn zoom_levels(&self) -> i32 {
self.zoom_levels
}
pub fn mpp(&self) -> f64 {
self.image_cap_res
}
pub fn channels(&self) -> &[ChannelMetadata] {
&self.channels
}
}
pub(crate) type DecodedTile = (TileInfo, Vec<u8>, u64, u64);
pub(crate) type DecodedLevels = Vec<Vec<DecodedTile>>;
#[derive(Debug)]
pub(crate) struct DecodedAssociatedImage {
pub kind: AssociatedImageKind,
pub pixels: Vec<u8>,
pub width: u64,
pub height: u64,
}
#[derive(Debug, Clone)]
pub struct TileInfo {
pub(crate) pos_x: i32,
pub(crate) pos_y: i32,
width: i32,
height: i32,
channel_index: usize,
pub(crate) zoom_level: i32,
pub(crate) data_offset: u64,
pub(crate) data_length: i32,
}
pub(crate) struct TileInfoFields {
pub pos_x: i32,
pub pos_y: i32,
pub width: i32,
pub height: i32,
pub channel_index: usize,
pub zoom_level: i32,
pub data_offset: u64,
pub data_length: i32,
}
impl TileInfo {
pub(crate) fn new(
pos_x: i32,
pos_y: i32,
width: i32,
height: i32,
zoom_level: i32,
data_offset: u64,
data_length: i32,
) -> Self {
Self::from_fields(TileInfoFields {
pos_x,
pos_y,
width,
height,
channel_index: 0,
zoom_level,
data_offset,
data_length,
})
}
pub(crate) fn from_fields(fields: TileInfoFields) -> Self {
Self {
pos_x: fields.pos_x,
pos_y: fields.pos_y,
width: fields.width,
height: fields.height,
channel_index: fields.channel_index,
zoom_level: fields.zoom_level,
data_offset: fields.data_offset,
data_length: fields.data_length,
}
}
pub fn pos_x(&self) -> i32 {
self.pos_x
}
pub fn pos_y(&self) -> i32 {
self.pos_y
}
pub fn width(&self) -> i32 {
self.width
}
pub fn height(&self) -> i32 {
self.height
}
pub fn channel_index(&self) -> usize {
self.channel_index
}
pub fn zoom_level(&self) -> i32 {
self.zoom_level
}
}
#[derive(Debug, Clone)]
pub struct AssociatedImage {
kind: AssociatedImageKind,
width: i32,
height: i32,
pub(crate) data_offset: u64,
pub(crate) data_length: i32,
}
impl AssociatedImage {
pub(crate) fn new(
kind: AssociatedImageKind,
width: i32,
height: i32,
data_offset: u64,
data_length: i32,
) -> Self {
Self {
kind,
width,
height,
data_offset,
data_length,
}
}
pub fn kind(&self) -> AssociatedImageKind {
self.kind
}
pub fn width(&self) -> i32 {
self.width
}
pub fn height(&self) -> i32 {
self.height
}
}