| 250 | } |
| 251 | |
| 252 | fn write_heatmap( |
| 253 | reference: &[[f32; 3]], |
| 254 | candidate: &[[f32; 3]], |
| 255 | width: u32, |
| 256 | height: u32, |
| 257 | path: &Path, |
| 258 | ) -> Result<(), String> { |
| 259 | let mut img: RgbImage = ImageBuffer::new(width, height); |
| 260 | for y in 0..height { |
| 261 | for x in 0..width { |
| 262 | let i = (y * width + x) as usize; |
| 263 | let dr = (reference[i][0] - candidate[i][0]).abs(); |
| 264 | let dg = (reference[i][1] - candidate[i][1]).abs(); |
| 265 | let db = (reference[i][2] - candidate[i][2]).abs(); |
| 266 | let mag = dr.max(dg).max(db); |
| 267 | img.put_pixel(x, y, heatmap_color(mag)); |
| 268 | } |
| 269 | } |
| 270 | img.save(path).map_err(|e| format!("save {:?}: {e}", path)) |
| 271 | } |
| 272 | |
| 273 | fn write_composite( |
| 274 | reference_img: &RgbImage, |