contributionBetween function

PassContribution contributionBetween(
  1. ByteData without,
  2. ByteData with_, {
  3. required int width,
  4. required int height,
})

Differences two RGBA frames of width by height.

Alpha is deliberately not compared. Every frame this engine hands back is opaque, so a difference there would be a bug in the readback rather than a contribution from a pass, and counting it would put a constant under every measurement.

Implementation

PassContribution contributionBetween(
  ByteData without,
  ByteData with_, {
  required int width,
  required int height,
}) {
  final pixels = width * height;
  if (without.lengthInBytes != pixels * 4 ||
      with_.lengthInBytes != pixels * 4) {
    throw ArgumentError(
      'the two frames must both be $width x $height RGBA — got '
      '${without.lengthInBytes} and ${with_.lengthInBytes} bytes, and a '
      'difference between frames of different sizes is not a contribution',
    );
  }

  var changed = 0;
  var worst = 0;
  var sum = 0;
  var left = width;
  var top = height;
  var right = -1;
  var bottom = -1;

  for (var i = 0; i < pixels; i++) {
    final at = i * 4;
    var most = 0;
    for (var c = 0; c < 3; c++) {
      final delta = (without.getUint8(at + c) - with_.getUint8(at + c)).abs();
      if (delta > most) most = delta;
    }
    if (most == 0) continue;

    changed++;
    sum += most;
    if (most > worst) worst = most;

    final x = i % width;
    final y = i ~/ width;
    if (x < left) left = x;
    if (x > right) right = x;
    if (y < top) top = y;
    if (y > bottom) bottom = y;
  }

  return PassContribution(
    changedPixels: changed,
    totalPixels: pixels,
    worstChannelDelta: worst,
    meanChannelDelta: changed == 0 ? 0.0 : sum / changed,
    bounds: changed == 0
        ? null
        : (left: left, top: top, right: right, bottom: bottom),
  );
}