Skip to content

Commit 20b3091

Browse files
committed
(#500) Implement color finder interface + tests
1 parent cd03e9c commit 20b3091

File tree

4 files changed

+141
-0
lines changed

4 files changed

+141
-0
lines changed

e2e/assets/dot.png

413 Bytes
Loading

e2e/assets/dots.png

424 Bytes
Loading
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import ColorFinder from "./color-finder.class";
2+
import { join } from "path";
3+
import {
4+
ColorQuery,
5+
loadImage,
6+
MatchRequest,
7+
MatchResult,
8+
Point,
9+
RGBA,
10+
} from "../../../index";
11+
12+
describe("color finder", () => {
13+
describe("find", () => {
14+
it("should resolve", async () => {
15+
// GIVEN
16+
const screenImage = await loadImage(
17+
join(__dirname, `../../../e2e/assets/dot.png`)
18+
);
19+
const SUT = new ColorFinder();
20+
const colorQuery: ColorQuery = {
21+
id: "colorFinderTest",
22+
type: "color",
23+
by: {
24+
color: new RGBA(255, 0, 0, 255),
25+
},
26+
};
27+
const matchRequest = new MatchRequest(screenImage, colorQuery, 0.9);
28+
29+
const expectedResult = new MatchResult(1, new Point(60, 60));
30+
31+
// WHEN
32+
const result = await SUT.findMatch(matchRequest);
33+
34+
// THEN
35+
expect(result).toEqual(expectedResult);
36+
});
37+
});
38+
39+
describe("findAll", () => {
40+
it("should resolve", async () => {
41+
// GIVEN
42+
const screenImage = await loadImage(
43+
join(__dirname, `../../../e2e/assets/dots.png`)
44+
);
45+
const SUT = new ColorFinder();
46+
const colorQuery: ColorQuery = {
47+
id: "colorFinderTest",
48+
type: "color",
49+
by: {
50+
color: new RGBA(255, 0, 0, 255),
51+
},
52+
};
53+
const matchRequest = new MatchRequest(screenImage, colorQuery, 0.9);
54+
55+
const expectedResult = [
56+
new MatchResult(1, new Point(60, 60)),
57+
new MatchResult(1, new Point(60, 80)),
58+
new MatchResult(1, new Point(60, 100)),
59+
];
60+
61+
// WHEN
62+
const result = await SUT.findMatches(matchRequest);
63+
64+
// THEN
65+
expect(result).toEqual(expectedResult);
66+
});
67+
});
68+
});
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import { ColorFinderInterface } from "../color-finder.interface";
2+
import { MatchRequest } from "../../match-request.class";
3+
import { ColorQuery } from "../../query.class";
4+
import { MatchResult } from "../../match-result.class";
5+
import { imageToJimp } from "../io/imageToJimp.function";
6+
import { Point } from "../../point.class";
7+
8+
export default class implements ColorFinderInterface {
9+
async findMatch<PROVIDER_DATA_TYPE>(
10+
query: MatchRequest<ColorQuery, PROVIDER_DATA_TYPE>
11+
): Promise<MatchResult<Point>> {
12+
const jimp = imageToJimp(query.haystack);
13+
let result: MatchResult<Point> | null = null;
14+
const color = query.needle.by.color;
15+
for (const { x, y, idx } of jimp.scanIterator(
16+
0,
17+
0,
18+
jimp.bitmap.width,
19+
jimp.bitmap.height
20+
)) {
21+
if (
22+
jimp.bitmap.data[idx] === color.R &&
23+
jimp.bitmap.data[idx + 1] === color.G &&
24+
jimp.bitmap.data[idx + 2] === color.B &&
25+
jimp.bitmap.data[idx + 3] === color.A
26+
) {
27+
result = new MatchResult(
28+
1,
29+
new Point(
30+
x / query.haystack.pixelDensity.scaleX,
31+
y / query.haystack.pixelDensity.scaleY
32+
)
33+
);
34+
break;
35+
}
36+
}
37+
38+
if (result) {
39+
return result;
40+
} else {
41+
throw new Error(
42+
`No match for color RGBA(${color.R},${color.G},${color.B},${color.A}) found`
43+
);
44+
}
45+
}
46+
47+
async findMatches<PROVIDER_DATA_TYPE>(
48+
query: MatchRequest<ColorQuery, PROVIDER_DATA_TYPE>
49+
): Promise<MatchResult<Point>[]> {
50+
const jimp = imageToJimp(query.haystack);
51+
const results: MatchResult<Point>[] = [];
52+
const color = query.needle.by.color;
53+
jimp.scan(0, 0, jimp.bitmap.width, jimp.bitmap.height, (x, y, idx) => {
54+
if (
55+
jimp.bitmap.data[idx] === color.R &&
56+
jimp.bitmap.data[idx + 1] === color.G &&
57+
jimp.bitmap.data[idx + 2] === color.B &&
58+
jimp.bitmap.data[idx + 3] === color.A
59+
) {
60+
results.push(
61+
new MatchResult(
62+
1,
63+
new Point(
64+
x / query.haystack.pixelDensity.scaleX,
65+
y / query.haystack.pixelDensity.scaleY
66+
)
67+
)
68+
);
69+
}
70+
});
71+
return results;
72+
}
73+
}

0 commit comments

Comments
 (0)