Skip to content
This repository was archived by the owner on Jul 26, 2025. It is now read-only.

Commit bc5437a

Browse files
authored
chore: improve alignMinDifference (#389)
Original code: 1700 ms Avoiding the creation of images: 1200 ms Changing Math.abs to if / else : 200 ms
1 parent afecc5f commit bc5437a

File tree

3 files changed

+34
-19
lines changed

3 files changed

+34
-19
lines changed

src/align/__tests__/alignMinDifference.test.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,5 @@ test('other id crops', () => {
9696
const result = alignMinDifference(source, destination);
9797

9898
const overlap = overlapImages(source, destination, { origin: result });
99-
10099
expect(overlap).toMatchImageSnapshot();
101100
});

src/align/alignMinDifference.ts

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { Image, ImageColorModel, Point } from '..';
2-
import { subtract } from '../compare/subtract';
32

43
export interface AlignMinDifferenceOptions {
54
/**
@@ -46,7 +45,7 @@ export function alignMinDifference(
4645
destination = destination.grey();
4746
}
4847

49-
let bestMean = Number.POSITIVE_INFINITY;
48+
let bestDifference = Number.POSITIVE_INFINITY;
5049
let bestShiftX = 0;
5150
let bestShiftY = 0;
5251

@@ -60,18 +59,29 @@ export function alignMinDifference(
6059

6160
for (let shiftX = startX; shiftX <= endX; shiftX += step) {
6261
for (let shiftY = startY; shiftY <= endY; shiftY += step) {
63-
const destinationCropped = destination.crop({
64-
origin: { row: shiftY, column: shiftX },
65-
width: source.width,
66-
height: source.height,
67-
});
68-
69-
const imagesDiff = subtract(source, destinationCropped, {
70-
absolute: true,
71-
});
72-
const mean = imagesDiff.mean()[0];
73-
if (mean < bestMean) {
74-
bestMean = mean;
62+
let currentDifference = 0;
63+
next: for (let column = 0; column < source.width; column++) {
64+
for (let row = 0; row < source.height; row++) {
65+
const sourceValue = source.getValue(column, row, 0);
66+
const destinationValue = destination.getValue(
67+
column + shiftX,
68+
row + shiftY,
69+
0,
70+
);
71+
const difference = sourceValue - destinationValue;
72+
if (difference < 0) {
73+
// Math.abs is super slow, this simple trick is 5x faster
74+
currentDifference -= difference;
75+
} else {
76+
currentDifference += difference;
77+
}
78+
if (currentDifference > bestDifference) {
79+
break next;
80+
}
81+
}
82+
}
83+
if (currentDifference < bestDifference) {
84+
bestDifference = currentDifference;
7585
bestShiftX = shiftX;
7686
bestShiftY = shiftY;
7787
}

src/compare/subtract.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,15 @@ export function subtract(
5757
image.getValueByIndex(index, channel) -
5858
otherImage.getValueByIndex(index, channel);
5959
if (absolute) {
60-
newImage.setValueByIndex(index, channel, Math.abs(value));
60+
if (value < 0) {
61+
newImage.setValueByIndex(index, channel, -value);
62+
} else {
63+
newImage.setValueByIndex(index, channel, value);
64+
}
65+
} else if (value < 0) {
66+
newImage.setValueByIndex(index, channel, 0);
6167
} else {
62-
newImage.setValueByIndex(index, channel, Math.max(value, 0));
68+
newImage.setValueByIndex(index, channel, value);
6369
}
6470
}
6571
}
@@ -68,9 +74,9 @@ export function subtract(
6874
const value =
6975
image.getBitByIndex(index) - otherImage.getBitByIndex(index);
7076
if (absolute) {
71-
newImage.setBitByIndex(index, Math.abs(value) ? 1 : 0);
77+
newImage.setBitByIndex(index, value ? 1 : 0);
7278
} else {
73-
newImage.setBitByIndex(index, Math.max(value, 0) ? 1 : 0);
79+
newImage.setBitByIndex(index, value > 0 ? 1 : 0);
7480
}
7581
}
7682
}

0 commit comments

Comments
 (0)