pub mod settings;
use crate::settings::{GenerateDensityImageSettings, ImageDensitySource};
use density_mesh_core::{
map::{DensityMap, DensityMapError},
Scalar,
};
use image::{imageops::FilterType, DynamicImage, GenericImageView, GrayImage};
pub fn generate_densitymap_image(
image: DynamicImage,
settings: &GenerateDensityImageSettings,
steepness: bool,
) -> Result<DynamicImage, DensityMapError> {
let map = generate_densitymap_from_image(image, settings)?;
let data = if steepness {
map.steepness()
.iter()
.map(|v| (v * 255.0) as u8)
.collect::<Vec<_>>()
} else {
map.values()
.iter()
.map(|v| (v * 255.0) as u8)
.collect::<Vec<_>>()
};
Ok(DynamicImage::ImageLuma8(
GrayImage::from_raw(map.unscaled_width() as _, map.unscaled_height() as _, data).unwrap(),
))
}
pub fn generate_densitymap_from_image(
image: DynamicImage,
settings: &GenerateDensityImageSettings,
) -> Result<DensityMap, DensityMapError> {
let scale = settings.scale.max(1);
let image = if scale > 1 {
image.resize_exact(
image.width() / scale as u32,
image.height() / scale as u32,
FilterType::Lanczos3,
)
} else {
image
};
match settings.density_source {
ImageDensitySource::Luma => {
let img = image.to_luma();
DensityMap::new(img.width() as _, img.height() as _, scale, img.into_raw())
}
ImageDensitySource::LumaAlpha => {
let w = image.width();
let h = image.height();
let img = image.to_luma_alpha();
let data = img
.into_raw()
.chunks(2)
.map(|c| ((c[0] as Scalar / 255.0) * (c[1] as Scalar / 255.0) * 255.0) as u8)
.collect::<Vec<_>>();
DensityMap::new(w as _, h as _, scale, data)
}
ImageDensitySource::Red => {
let w = image.width();
let h = image.height();
let data = image
.to_rgba()
.into_raw()
.chunks(4)
.map(|c| c[0])
.collect::<Vec<_>>();
DensityMap::new(w as _, h as _, scale, data)
}
ImageDensitySource::Green => {
let w = image.width();
let h = image.height();
let data = image
.to_rgba()
.into_raw()
.chunks(4)
.map(|c| c[1])
.collect::<Vec<_>>();
DensityMap::new(w as _, h as _, scale, data)
}
ImageDensitySource::Blue => {
let w = image.width();
let h = image.height();
let data = image
.to_rgba()
.into_raw()
.chunks(4)
.map(|c| c[2])
.collect::<Vec<_>>();
DensityMap::new(w as _, h as _, scale, data)
}
ImageDensitySource::Alpha => {
let w = image.width();
let h = image.height();
let data = image
.to_rgba()
.into_raw()
.chunks(4)
.map(|c| c[3])
.collect::<Vec<_>>();
DensityMap::new(w as _, h as _, scale, data)
}
}
}
pub fn generate_image_from_densitymap(map: &DensityMap, steepness: bool) -> DynamicImage {
DynamicImage::ImageLuma8(
GrayImage::from_raw(
map.unscaled_width() as _,
map.unscaled_height() as _,
if steepness {
map.steepness()
.iter()
.map(|v| (v * 255.0) as u8)
.collect::<Vec<_>>()
} else {
map.values()
.iter()
.map(|v| (v * 255.0) as u8)
.collect::<Vec<_>>()
},
)
.unwrap(),
)
}
pub mod prelude {
pub use crate::{
generate_densitymap_from_image, generate_densitymap_image, generate_image_from_densitymap,
settings::*,
};
}