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

Commit 58041ea

Browse files
authored
fix: correct level default options and rename autoLevel to increaseContrast (#409)
Closes: #166 level now has default options which will increase the constrast BREAKING CHANGE: renamed autoLevel to increaseContrast
1 parent 646dc2b commit 58041ea

File tree

8 files changed

+54
-38
lines changed

8 files changed

+54
-38
lines changed

src/Image.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ import {
4343
InvertOptions,
4444
level,
4545
LevelOptions,
46-
autoLevel,
47-
AutoLevelOptions,
46+
increaseContrast,
47+
IncreaseContrastOptions,
4848
pixelate,
4949
PixelateOptions,
5050
medianFilter,
@@ -938,12 +938,12 @@ export class Image {
938938
}
939939

940940
/**
941-
* Enhance the contrast of an image by spanning each channel on the range [0, image.maxValue].
942-
* @param options - Enhance contrast options.
941+
* Increase the contrast of an image by spanning each channel on the range [0, image.maxValue].
942+
* @param options - Increase contrast options.
943943
* @returns The enhanced image.
944944
*/
945-
public autoLevel(options: AutoLevelOptions = {}): Image {
946-
return autoLevel(this, options);
945+
public increaseContrast(options: IncreaseContrastOptions = {}): Image {
946+
return increaseContrast(this, options);
947947
}
948948

949949
/**
45.7 KB
Loading

src/filters/__tests__/autoLevel.test.ts renamed to src/filters/__tests__/increaseContrast.test.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { autoLevel } from '../autoLevel';
1+
import { increaseContrast } from '../increaseContrast';
22

33
test('3x1 rgba image, custom output min and max', () => {
44
const image = testUtils.createRgbaImage([
@@ -7,7 +7,7 @@ test('3x1 rgba image, custom output min and max', () => {
77
[255, 200, 0, 50],
88
]);
99

10-
const result = autoLevel(image);
10+
const result = increaseContrast(image);
1111

1212
expect(result).toMatchImageData([
1313
[0, 0, 0, 50],
@@ -23,7 +23,7 @@ test('3x1 rgba image, uniform = true, image should not change', () => {
2323
[255, 200, 0, 50],
2424
]);
2525

26-
const result = autoLevel(image, { uniform: true });
26+
const result = increaseContrast(image, { uniform: true });
2727

2828
expect(result).toMatchImage(image);
2929
});
@@ -35,7 +35,7 @@ test('3x1 rgb image, uniform = true', () => {
3535
[200, 200, 0],
3636
]);
3737

38-
const result = autoLevel(image, { uniform: true });
38+
const result = increaseContrast(image, { uniform: true });
3939
expect(result).toMatchImageData([
4040
[0, 127, 0],
4141
[191, 191, 0],
@@ -45,15 +45,15 @@ test('3x1 rgb image, uniform = true', () => {
4545

4646
test('1x3 grey image', () => {
4747
const image = testUtils.createGreyImage([[50, 100]]);
48-
expect(autoLevel(image)).toMatchImageData([[0, 255]]);
48+
expect(increaseContrast(image)).toMatchImageData([[0, 255]]);
4949
});
5050

5151
test('alpha should not be modified', () => {
5252
const image = testUtils.createGreyaImage([
5353
[50, 100],
5454
[100, 50],
5555
]);
56-
expect(autoLevel(image)).toMatchImageData([
56+
expect(increaseContrast(image)).toMatchImageData([
5757
[0, 100],
5858
[255, 50],
5959
]);
@@ -65,7 +65,7 @@ test('out option', () => {
6565
[30, 40],
6666
[60, 70],
6767
]);
68-
const result = autoLevel(image, { out: image });
68+
const result = increaseContrast(image, { out: image });
6969
expect(result).toMatchImageData([
7070
[0, 10],
7171
[127, 40],
@@ -75,6 +75,6 @@ test('out option', () => {
7575
});
7676

7777
test('bigger image', () => {
78-
const image = testUtils.load('featureMatching/id-crops/crop1.png');
79-
expect(autoLevel(image)).toMatchImageSnapshot();
78+
const image = testUtils.load('featureMatching/id-crops/crop2.png');
79+
expect(increaseContrast(image)).toMatchImageSnapshot();
8080
});

src/filters/__tests__/level.test.ts

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,25 @@
1-
test('1x1 rgba image, default options', () => {
2-
const image = testUtils.createRgbaImage([[100, 0, 0, 50]]);
3-
expect(image.level()).toMatchImage(image);
1+
test('3x1 rgba image, default options', () => {
2+
// should span contrast on the whole range
3+
const image = testUtils.createRgbaImage([
4+
[1, 0, 1, 50],
5+
[2, 2, 0, 50],
6+
[3, 1, 0, 50],
7+
]);
8+
expect(image.level()).toMatchImageData([
9+
[0, 0, 255, 50],
10+
[127, 255, 0, 50],
11+
[255, 127, 0, 50],
12+
]);
413
});
514

615
test('1x1 rgba image, out to itself', () => {
7-
const image = testUtils.createRgbaImage([[100, 0, 0, 50]]);
16+
const image = testUtils.createRgbaImage([[100, 50, 0, 50]]);
817
expect(image.level({ out: image })).toBe(image);
918
});
1019

11-
test('1x1 greya image, default options', () => {
20+
test('1x4 greya image, default options', () => {
1221
const image = testUtils.createRgbaImage([[100, 50, 0, 50]]);
13-
expect(image.level()).toMatchImage(image);
22+
expect(image.level()).toMatchImageData([[0, 0, 0, 50]]);
1423
});
1524

1625
test('3x1 rgba image, custom input min and max', () => {
@@ -29,12 +38,12 @@ test('3x1 rgba image, custom input min and max', () => {
2938
test('3x1 rgba image, custom output min and max', () => {
3039
const image = testUtils.createRgbaImage([
3140
[0, 0, 0, 50],
32-
[127, 0, 0, 50],
41+
[127, 1, 0, 50],
3342
[255, 0, 0, 50],
3443
]);
3544
expect(image.level({ outputMin: 100, outputMax: 150 })).toMatchImageData([
3645
[100, 100, 100, 50],
37-
[124, 100, 100, 50],
46+
[124, 150, 100, 50],
3847
[150, 100, 100, 50],
3948
]);
4049
});

src/filters/autoLevel.ts renamed to src/filters/increaseContrast.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { Image } from '../Image';
22
import { ImageColorModel } from '../utils/constants/colorModels';
33
import checkProcessable from '../utils/validators/checkProcessable';
44

5-
export interface AutoLevelOptions {
5+
export interface IncreaseContrastOptions {
66
/**
77
* Image to which to output.
88
*/
@@ -15,12 +15,16 @@ export interface AutoLevelOptions {
1515
}
1616

1717
/**
18-
* Enhance the contrast of an image by spanning each channel on the range [0, image.maxValue].
18+
* Increase the contrast of an image by spanning each channel on the range [0, image.maxValue].
19+
* This algorithm is based on the level algorithm.
1920
* @param image - The image to enhance.
20-
* @param options - Enhance contrast options.
21+
* @param options - Increase contrast options.
2122
* @returns The enhanced image.
2223
*/
23-
export function autoLevel(image: Image, options: AutoLevelOptions = {}): Image {
24+
export function increaseContrast(
25+
image: Image,
26+
options: IncreaseContrastOptions = {},
27+
): Image {
2428
const { uniform = false } = options;
2529
checkProcessable(image, {
2630
bitDepth: [8, 16],

src/filters/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ export * from './and';
22
export * from './blur';
33
export * from './convolution';
44
export * from './derivativeFilter';
5-
export * from './autoLevel';
5+
export * from './increaseContrast';
66
export * from './gaussianBlur';
77
export * from './gradientFilter';
88
export * from './hypotenuse';

src/filters/level.ts

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,22 @@ export interface LevelOptions {
1212
*/
1313
channels?: number[];
1414
/**
15-
* Minimal input value.
16-
* @default `0`
15+
* Input lower bound.
16+
* @default `image.minMax().min`
1717
*/
1818
inputMin?: number | number[];
1919
/**
20-
* Maximal input value.
21-
* @default `image.maxValue`
20+
* Input upper bound.
21+
* @default `image.minMax().min`
2222
*/
2323
inputMax?: number | number[];
2424
/**
25-
* Minimal output value.
25+
* output lower bound.
2626
* @default `0`
2727
*/
2828
outputMin?: number | number[];
2929
/**
30-
* Maximal output value.
30+
* Output upper bound.
3131
* @default `image.maxValue`
3232
*/
3333
outputMax?: number | number[];
@@ -43,15 +43,16 @@ export interface LevelOptions {
4343
}
4444

4545
/**
46-
* Level the image using the optional input and output value. This function allows you to enhance the image's contrast.
46+
* Level the image using the optional input and output value. The default options allow to increase the image's contrast.
4747
* @param image - Image to process.
4848
* @param options - Level options.
4949
* @returns The levelled image.
5050
*/
5151
export function level(image: Image, options: LevelOptions = {}) {
52+
const minMax = image.minMax();
5253
let {
53-
inputMin = 0,
54-
inputMax = image.maxValue,
54+
inputMin = minMax.min,
55+
inputMax = minMax.max,
5556
outputMin = 0,
5657
outputMax = image.maxValue,
5758
gamma = 1,
@@ -86,11 +87,13 @@ export function level(image: Image, options: LevelOptions = {}) {
8687
inputMin[channel],
8788
);
8889

89-
const ratio = clamp(
90+
let ratio = clamp(
9091
(clamped - inputMin[channel]) /
9192
(inputMax[channel] - inputMin[channel]),
9293
);
9394

95+
if (Number.isNaN(ratio)) ratio = 0;
96+
9497
const result = clamp(
9598
ratio ** (1 / gamma[channel]) *
9699
(outputMax[channel] - outputMin[channel]) +

0 commit comments

Comments
 (0)