@@ -17,31 +17,31 @@ export interface LevelOptions {
17
17
*
18
18
* @default 0
19
19
*/
20
- inputMin ?: number ;
20
+ inputMin ?: number | number [ ] ;
21
21
/**
22
22
* Maximal input value.
23
23
*
24
24
* @default image.maxValue
25
25
*/
26
- inputMax ?: number ;
26
+ inputMax ?: number | number [ ] ;
27
27
/**
28
28
* Minimal output value.
29
29
*
30
30
* @default 0
31
31
*/
32
- outputMin ?: number ;
32
+ outputMin ?: number | number [ ] ;
33
33
/**
34
34
* Maximal output value.
35
35
*
36
36
* @default image.maxValue
37
37
*/
38
- outputMax ?: number ;
38
+ outputMax ?: number | number [ ] ;
39
39
/**
40
40
* Specifies the shape of the curve connecting the two points.
41
41
*
42
42
* @default 1
43
43
*/
44
- gamma ?: number ;
44
+ gamma ?: number | number [ ] ;
45
45
/**
46
46
* Image to which to output.
47
47
*/
@@ -75,17 +75,31 @@ export function level(image: Image, options: LevelOptions = {}) {
75
75
76
76
const clamp = getClamp ( image ) ;
77
77
78
+ inputMin = getValueArray ( inputMin , image . channels ) ;
79
+ inputMax = getValueArray ( inputMax , image . channels ) ;
80
+ outputMin = getValueArray ( outputMin , image . channels ) ;
81
+ outputMax = getValueArray ( outputMax , image . channels ) ;
82
+ gamma = getValueArray ( gamma , image . channels ) ;
83
+
78
84
for ( let row = 0 ; row < image . height ; row ++ ) {
79
85
for ( let column = 0 ; column < image . width ; column ++ ) {
80
86
for ( let channel of channels ) {
81
87
let currentValue = image . getValue ( column , row , channel ) ;
82
88
83
- let clamped = Math . max ( Math . min ( currentValue , inputMax ) , inputMin ) ;
89
+ let clamped = Math . max (
90
+ Math . min ( currentValue , inputMax [ channel ] ) ,
91
+ inputMin [ channel ] ,
92
+ ) ;
84
93
85
- const ratio = clamp ( ( clamped - inputMin ) / ( inputMax - inputMin ) ) ;
94
+ const ratio = clamp (
95
+ ( clamped - inputMin [ channel ] ) /
96
+ ( inputMax [ channel ] - inputMin [ channel ] ) ,
97
+ ) ;
86
98
87
99
const result = clamp (
88
- ratio ** ( 1 / gamma ) * ( outputMax - outputMin ) + outputMin ,
100
+ ratio ** ( 1 / gamma [ channel ] ) *
101
+ ( outputMax [ channel ] - outputMin [ channel ] ) +
102
+ outputMin [ channel ] ,
89
103
) ;
90
104
91
105
newImage . setValue ( column , row , channel , result ) ;
@@ -94,3 +108,25 @@ export function level(image: Image, options: LevelOptions = {}) {
94
108
}
95
109
return newImage ;
96
110
}
111
+
112
+ /**
113
+ * Get an array with correct values for each channel to process.
114
+ *
115
+ * @param value - Number or array to transform to the final array.
116
+ * @param imageChannels - Number of channels processed in the level function.
117
+ * @returns Array of values for each channel.
118
+ */
119
+ function getValueArray (
120
+ value : number | number [ ] ,
121
+ imageChannels : number ,
122
+ ) : number [ ] {
123
+ if ( Array . isArray ( value ) ) {
124
+ if ( value . length === imageChannels ) {
125
+ return value ;
126
+ } else {
127
+ throw new Error ( 'array length is not compatible with channel option' ) ;
128
+ }
129
+ } else {
130
+ return new Array ( imageChannels ) . fill ( value ) ;
131
+ }
132
+ }
0 commit comments