changed property

bool get changed

Whether this counts as a change at all.

Two thresholds rather than one, because they catch different lies. A fraction alone misses a moved 8px icon in a tall screen; a cluster alone fires on a single stray pixel that no eye would find. Something has to pass one of them, or the pictures are the same picture.

Implementation

bool get changed =>
    sizeChanged ||
    fraction >= fractionThreshold ||
    clusters.any((c) => c.area >= clusterThreshold);