density_mesh_image/
lib.rs1pub mod settings;
2
3use crate::settings::{GenerateDensityImageSettings, ImageDensitySource};
4use density_mesh_core::{
5 map::{DensityMap, DensityMapError},
6 Scalar,
7};
8use image::{imageops::FilterType, DynamicImage, GenericImageView, GrayImage};
9
10pub fn generate_densitymap_image(
20 image: DynamicImage,
21 settings: &GenerateDensityImageSettings,
22 steepness: bool,
23) -> Result<DynamicImage, DensityMapError> {
24 let map = generate_densitymap_from_image(image, settings)?;
25 let data = if steepness {
26 map.steepness()
27 .iter()
28 .map(|v| (v * 255.0) as u8)
29 .collect::<Vec<_>>()
30 } else {
31 map.values()
32 .iter()
33 .map(|v| (v * 255.0) as u8)
34 .collect::<Vec<_>>()
35 };
36 Ok(DynamicImage::ImageLuma8(
37 GrayImage::from_raw(map.unscaled_width() as _, map.unscaled_height() as _, data).unwrap(),
38 ))
39}
40
41pub fn generate_densitymap_from_image(
50 image: DynamicImage,
51 settings: &GenerateDensityImageSettings,
52) -> Result<DensityMap, DensityMapError> {
53 let scale = settings.scale.max(1);
54 let image = if scale > 1 {
55 image.resize_exact(
56 image.width() / scale as u32,
57 image.height() / scale as u32,
58 FilterType::Lanczos3,
59 )
60 } else {
61 image
62 };
63 match settings.density_source {
64 ImageDensitySource::Luma => {
65 let img = image.to_luma();
66 DensityMap::new(img.width() as _, img.height() as _, scale, img.into_raw())
67 }
68 ImageDensitySource::LumaAlpha => {
69 let w = image.width();
70 let h = image.height();
71 let img = image.to_luma_alpha();
72 let data = img
73 .into_raw()
74 .chunks(2)
75 .map(|c| ((c[0] as Scalar / 255.0) * (c[1] as Scalar / 255.0) * 255.0) as u8)
76 .collect::<Vec<_>>();
77 DensityMap::new(w as _, h as _, scale, data)
78 }
79 ImageDensitySource::Red => {
80 let w = image.width();
81 let h = image.height();
82 let data = image
83 .to_rgba()
84 .into_raw()
85 .chunks(4)
86 .map(|c| c[0])
87 .collect::<Vec<_>>();
88 DensityMap::new(w as _, h as _, scale, data)
89 }
90 ImageDensitySource::Green => {
91 let w = image.width();
92 let h = image.height();
93 let data = image
94 .to_rgba()
95 .into_raw()
96 .chunks(4)
97 .map(|c| c[1])
98 .collect::<Vec<_>>();
99 DensityMap::new(w as _, h as _, scale, data)
100 }
101 ImageDensitySource::Blue => {
102 let w = image.width();
103 let h = image.height();
104 let data = image
105 .to_rgba()
106 .into_raw()
107 .chunks(4)
108 .map(|c| c[2])
109 .collect::<Vec<_>>();
110 DensityMap::new(w as _, h as _, scale, data)
111 }
112 ImageDensitySource::Alpha => {
113 let w = image.width();
114 let h = image.height();
115 let data = image
116 .to_rgba()
117 .into_raw()
118 .chunks(4)
119 .map(|c| c[3])
120 .collect::<Vec<_>>();
121 DensityMap::new(w as _, h as _, scale, data)
122 }
123 }
124}
125
126pub fn generate_image_from_densitymap(map: &DensityMap, steepness: bool) -> DynamicImage {
135 DynamicImage::ImageLuma8(
136 GrayImage::from_raw(
137 map.unscaled_width() as _,
138 map.unscaled_height() as _,
139 if steepness {
140 map.steepness()
141 .iter()
142 .map(|v| (v * 255.0) as u8)
143 .collect::<Vec<_>>()
144 } else {
145 map.values()
146 .iter()
147 .map(|v| (v * 255.0) as u8)
148 .collect::<Vec<_>>()
149 },
150 )
151 .unwrap(),
152 )
153}
154
155pub mod prelude {
156 pub use crate::{
157 generate_densitymap_from_image, generate_densitymap_image, generate_image_from_densitymap,
158 settings::*,
159 };
160}