pmode: PMode,
}
+#[derive(Default)]
+struct LookupCache {
+ items: [(u8, [u8; 3]); 32],
+ fill: usize,
+}
+
+impl LookupCache {
+ fn lookup(&mut self, clr: [u8; 3]) -> Option<u8> {
+ for (idx, key) in self.items.iter().enumerate() {
+ if key.1 == clr {
+ let ret = key.0;
+ self.items.swap(0, idx);
+ return Some(ret);
+ }
+ }
+ None
+ }
+ fn add(&mut self, clr: [u8; 3], idx: u8) {
+ self.items[self.fill] = (idx, clr);
+ if self.fill < self.items.len() - 1 {
+ self.fill += 1;
+ }
+ }
+}
+
#[allow(dead_code)]
impl Palettiser {
pub fn new(mode: PaletteSearchMode, pal: &[[u8; 3]; 256]) -> Self {
if !ifmt.is_unpacked() {
let esize = ifmt.elem_size as usize;
let coffs = [ifmt.comp_info[0].unwrap().comp_offs as usize, ifmt.comp_info[1].unwrap().comp_offs as usize, ifmt.comp_info[2].unwrap().comp_offs as usize];
+ let mut cache = LookupCache::default();
match &self.pmode {
PMode::Full => {
for (src, dline) in sdata.chunks(istride)
for (pix, chunk) in dline.iter_mut()
.zip(src.chunks_exact(esize)).take(w) {
let spixel = [chunk[coffs[0]], chunk[coffs[1]], chunk[coffs[2]]];
- *pix = find_nearest(&spixel, &self.pal) as u8;
+ if let Some(idx) = cache.lookup(spixel) {
+ *pix = idx;
+ } else {
+ *pix = find_nearest(&spixel, &self.pal) as u8;
+ cache.add(spixel, *pix);
+ }
}
}
},
for (pix, chunk) in dline.iter_mut()
.zip(src.chunks_exact(esize)).take(w) {
let spixel = [chunk[coffs[0]], chunk[coffs[1]], chunk[coffs[2]]];
- *pix = ls.search(spixel) as u8;
+ if let Some(idx) = cache.lookup(spixel) {
+ *pix = idx;
+ } else {
+ *pix = ls.search(spixel) as u8;
+ cache.add(spixel, *pix);
+ }
}
}
},
for (pix, chunk) in dline.iter_mut()
.zip(src.chunks_exact(esize)).take(w) {
let spixel = [chunk[coffs[0]], chunk[coffs[1]], chunk[coffs[2]]];
- *pix = kdt.search(spixel) as u8;
+ if let Some(idx) = cache.lookup(spixel) {
+ *pix = idx;
+ } else {
+ *pix = kdt.search(spixel) as u8;
+ cache.add(spixel, *pix);
+ }
}
}
},