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

Commit 9f87a41

Browse files
committed
feat(autoLevel): add uniform option
Refs: https://github.com/zakodium/profid-padif-rework/issues/21
1 parent a6032d4 commit 9f87a41

File tree

2 files changed

+52
-2
lines changed

2 files changed

+52
-2
lines changed

src/filters/__tests__/autoLevel.test.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,33 @@ test('3x1 rgba image, custom output min and max', () => {
1616
]);
1717
});
1818

19+
test('3x1 rgba image, uniform = true, image should not change', () => {
20+
const image = testUtils.createRgbaImage([
21+
[0, 100, 0, 50],
22+
[127, 150, 0, 50],
23+
[255, 200, 0, 50],
24+
]);
25+
26+
const result = autoLevel(image, { uniform: true });
27+
28+
expect(result).toMatchImage(image);
29+
});
30+
31+
test('3x1 rgb image, uniform = true', () => {
32+
const image = testUtils.createRgbImage([
33+
[0, 100, 0],
34+
[150, 150, 0],
35+
[200, 200, 0],
36+
]);
37+
38+
const result = autoLevel(image, { uniform: true });
39+
expect(result).toMatchImageData([
40+
[0, 127, 0],
41+
[191, 191, 0],
42+
[255, 255, 0],
43+
]);
44+
});
45+
1946
test('1x3 grey image', () => {
2047
const image = testUtils.createGreyImage([[50, 100]]);
2148
expect(autoLevel(image)).toMatchImageData([[0, 255]]);

src/filters/autoLevel.ts

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ export interface AutoLevelOptions {
77
* Image to which to output.
88
*/
99
out?: Image;
10+
/**
11+
* Level all channels uniformly in order to preserve the color balance.
12+
* @default false
13+
*/
14+
uniform?: boolean;
1015
}
1116

1217
/**
@@ -16,11 +21,29 @@ export interface AutoLevelOptions {
1621
* @returns The enhanced image.
1722
*/
1823
export function autoLevel(image: Image, options: AutoLevelOptions = {}): Image {
24+
const { uniform = false } = options;
1925
checkProcessable(image, {
2026
bitDepth: [8, 16],
2127
});
2228
const minMax = image.minMax();
2329

30+
let min: number | number[] = minMax.min;
31+
let max: number | number[] = minMax.max;
32+
33+
if (uniform) {
34+
let minDiffIndex = -1;
35+
let previousDiff = -1;
36+
for (let i = 0; i < minMax.max.length; i++) {
37+
const difference = minMax.max[i] - minMax.min[i];
38+
if (difference > previousDiff) {
39+
minDiffIndex = i;
40+
previousDiff = difference;
41+
}
42+
}
43+
min = minMax.min[minDiffIndex];
44+
max = minMax.max[minDiffIndex];
45+
}
46+
2447
let channels: number[] = new Array(image.components)
2548
.fill(0)
2649
.map((value, index) => index);
@@ -32,8 +55,8 @@ export function autoLevel(image: Image, options: AutoLevelOptions = {}): Image {
3255
}
3356

3457
return image.level({
35-
inputMin: minMax.min,
36-
inputMax: minMax.max,
58+
inputMin: min,
59+
inputMax: max,
3760
outputMin: 0,
3861
outputMax: image.maxValue,
3962
channels,

0 commit comments

Comments
 (0)