/
hypotenuse.js
59 lines (53 loc) · 1.77 KB
/
hypotenuse.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
import { validateArrayOfChannels } from '../../util/channel';
import Image from '../Image';
/**
* Calculate a new image that is the hypotenuse between the current image and the otherImage.
* @memberof Image
* @instance
* @param {Image} otherImage
* @param {object} [options={}]
* @param {number} [options.bitDepth=this.bitDepth]
* @param {number[]|string[]} [options.channels] : to which channel to apply the filter. By default all but alpha.
* @return {Image}
*/
export default function hypotenuse(otherImage, options = {}) {
let { bitDepth = this.bitDepth, channels } = options;
this.checkProcessable('hypotenuse', {
bitDepth: [8, 16, 32],
});
if (this.width !== otherImage.width || this.height !== otherImage.height) {
throw new Error('hypotenuse: both images must have the same size');
}
if (
this.alpha !== otherImage.alpha ||
this.bitDepth !== otherImage.bitDepth
) {
throw new Error(
'hypotenuse: both images must have the same alpha and bitDepth',
);
}
if (this.channels !== otherImage.channels) {
throw new Error(
'hypotenuse: both images must have the same number of channels',
);
}
let newImage = Image.createFrom(this, { bitDepth: bitDepth });
channels = validateArrayOfChannels(this, { channels: channels });
let clamped = newImage.isClamped;
for (let j = 0; j < channels.length; j++) {
let c = channels[j];
for (let i = c; i < this.data.length; i += this.channels) {
let value = Math.hypot(this.data[i], otherImage.data[i]);
if (clamped) {
// we calculate the clamped result
newImage.data[i] = Math.min(
Math.max(Math.round(value), 0),
newImage.maxValue,
);
} else {
newImage.data[i] = value;
}
}
}
return newImage;
}