wsi-rs 0.4.0

wsi-rs whole-slide image reader
Documentation
use super::model::VmsLevel;
use super::*;

const VMS_SCALES: [u32; 3] = [2, 4, 8];

pub(super) fn expanded_levels(base_level: VmsLevel, map_level: VmsLevel) -> Vec<VmsLevel> {
    let mut levels_by_width = BTreeMap::new();
    for level in [base_level, map_level] {
        insert_scaled_levels(&mut levels_by_width, level);
    }
    levels_by_width
        .into_iter()
        .rev()
        .map(|(_, level)| level)
        .collect()
}

fn insert_scaled_levels(levels: &mut BTreeMap<u64, VmsLevel>, level: VmsLevel) {
    let width = base_level_dimensions(&level).0;
    levels.insert(width, level);
    let original = levels.get(&width).unwrap().clone_for_scale_base();
    for scale in VMS_SCALES {
        let tile_width = original.jpegs[0].tile_width;
        let tile_height = original.jpegs[0].tile_height;
        if !tile_width.is_multiple_of(scale) || !tile_height.is_multiple_of(scale) {
            continue;
        }
        levels.insert(
            base_level_dimensions(&original).0 / scale as u64,
            VmsLevel {
                scale_denom: scale,
                jpegs: original.jpegs.clone(),
                jpegs_across: original.jpegs_across,
                base_tiles_across: original.base_tiles_across,
                base_tiles_down: original.base_tiles_down,
            },
        );
    }
}

impl VmsLevel {
    fn clone_for_scale_base(&self) -> Self {
        Self {
            scale_denom: self.scale_denom,
            jpegs: self.jpegs.clone(),
            jpegs_across: self.jpegs_across,
            base_tiles_across: self.base_tiles_across,
            base_tiles_down: self.base_tiles_down,
        }
    }
}

pub(super) fn base_level_dimensions(level: &VmsLevel) -> (u64, u64) {
    let row_width: u64 = level
        .jpegs
        .iter()
        .take(level.jpegs_across as usize)
        .map(|jpeg| u64::from(jpeg.width))
        .sum();
    let col_height: u64 = level
        .jpegs
        .iter()
        .step_by(level.jpegs_across as usize)
        .map(|jpeg| u64::from(jpeg.height))
        .sum();
    (
        row_width / u64::from(level.scale_denom),
        col_height / u64::from(level.scale_denom),
    )
}

pub(super) fn total_tiles_across(level: &VmsLevel) -> u64 {
    level
        .jpegs
        .iter()
        .take(level.jpegs_across as usize)
        .map(|jpeg| u64::from(jpeg.tiles_across))
        .sum()
}

pub(super) fn total_tiles_down(level: &VmsLevel) -> u64 {
    level
        .jpegs
        .iter()
        .step_by(level.jpegs_across as usize)
        .map(|jpeg| u64::from(jpeg.tiles_down))
        .sum()
}