| 74 | } |
| 75 | |
| 76 | pub fn prepare_sort(&mut self) { |
| 77 | struct ChanVariance { |
| 78 | pub chan: usize, |
| 79 | pub variance: f32, |
| 80 | } |
| 81 | |
| 82 | // Sort dimensions by their variance, and then sort colors first by dimension with the highest variance |
| 83 | let vars: [f32; 4] = rgb::bytemuck::cast(self.variance); |
| 84 | let mut channels = [ |
| 85 | ChanVariance { chan: 0, variance: vars[0] }, |
| 86 | ChanVariance { chan: 1, variance: vars[1] }, |
| 87 | ChanVariance { chan: 2, variance: vars[2] }, |
| 88 | ChanVariance { chan: 3, variance: vars[3] }, |
| 89 | ]; |
| 90 | channels.sort_unstable_by_key(|ch| Reverse(OrdFloat::new(ch.variance))); |
| 91 | |
| 92 | for item in self.colors.iter_mut() { |
| 93 | let chans: [f32; 4] = rgb::bytemuck::cast(item.color.0); |
| 94 | // Only the first channel really matters. But other channels are included, because when trying median cut |
| 95 | // many times with different histogram weights, I don't want sort randomness to influence the outcome. |
| 96 | item.tmp.mc_sort_value = (u32::from((chans[channels[0].chan] * 65535.) as u16) << 16) |
| 97 | | u32::from(((chans[channels[2].chan] + chans[channels[1].chan] / 2. + chans[channels[3].chan] / 4.) * 65535.) as u16); // box will be split to make color_weight of each side even |
| 98 | } |
| 99 | } |
| 100 | |
| 101 | fn median_color(&mut self) -> f_pixel { |
| 102 | let len = self.colors.len(); |