+ fn calc_dist(&self, cur_frm: &[u8], xpos: usize, ypos: usize, cur_w: usize, cur_h: usize, bpp: usize) -> u32 {
+ let stride = self.width * bpp;
+ let mut diff = 0;
+ let roff = xpos * bpp + ypos * stride;
+ for (line0, line1) in cur_frm.chunks(stride).take(cur_h).zip(self.frm2[roff..].chunks(stride)) {
+ for (&a, &b) in line0[..cur_w * bpp].iter().zip(line1[..cur_w * bpp].iter()) {
+ diff += u32::from(a ^ b);
+ }
+ }
+ diff
+ }
+ fn motion_search(&self, cur_frm: &[u8], x: usize, y: usize, cur_w: usize, cur_h: usize, bpp: usize) -> (usize, usize, u32) {
+ let mut best_dist = self.calc_dist(cur_frm, x, y, cur_w, cur_h, bpp);
+ if best_dist == 0 {
+ return (x, y, 0);
+ }
+ let mut best_x = x;
+ let mut best_y = y;
+
+ if !self.full_me {
+ let mut cur_range = self.range.min(64);
+
+ while cur_range > 1 {
+ let x1 = best_x.saturating_sub(cur_range);
+ let x2 = (best_x + cur_range).min(self.width - cur_w);
+ let y1 = best_y.saturating_sub(cur_range);
+ let y2 = (best_y + cur_range).min(self.height - cur_h);
+ let points = [(best_x, y1),
+ (x2, y1),
+ (x2, best_y),
+ (x2, y2),
+ (best_x, y2),
+ (x1, y2),
+ (x1, best_y),
+ (x1, y1)];
+
+ for &(pt_x, pt_y) in points.iter() {
+ if ((x as isize) - (pt_x as isize)).abs() >= 64 {
+ continue;
+ }
+ if ((y as isize) - (pt_y as isize)).abs() >= 64 {
+ continue;
+ }
+ let dist = self.calc_dist(cur_frm, pt_x, pt_y, cur_w, cur_h, bpp);
+ if dist < best_dist {
+ best_dist = dist;
+ best_x = pt_x;
+ best_y = pt_y;
+ }
+ }
+ cur_range = (cur_range + 1) >> 1;
+ }
+ } else {
+ for yoff in 0..self.range {
+ let ypos = (y as isize) + to_signed(yoff);
+ if ypos < 0 {
+ continue;
+ }
+ let ypos = ypos as usize;
+ if ypos + cur_h > self.height {
+ break;
+ }
+ for xoff in 0..self.range {
+ let xpos = (x as isize) + to_signed(xoff);
+ if xpos < 0 {
+ continue;
+ }
+ let xpos = xpos as usize;
+ if xpos + cur_w > self.width {
+ break;
+ }
+
+ let diff = self.calc_dist(cur_frm, xpos, ypos, cur_w, cur_h, bpp);
+
+ if best_dist > diff {
+ best_dist = diff;
+ best_x = xpos;
+ best_y = ypos;
+ if diff == 0 {
+ return (best_x, best_y, 0);
+ }
+ }
+ }
+ }
+ }
+ (best_x, best_y, best_dist)
+ }