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

Commit 09621e5

Browse files
feat: add a sum operation (#384)
1 parent e10ab1e commit 09621e5

File tree

4 files changed

+105
-1
lines changed

4 files changed

+105
-1
lines changed

src/Image.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { RgbColor } from 'colord';
22

33
import { Mask } from './Mask';
4-
import { subtract, SubtractImageOptions } from './compare';
4+
import { subtract, add, SubtractImageOptions } from './compare';
55
import { median } from './compute/median';
66
import { variance } from './compute/variance';
77
import { correctColor } from './correctColor';
@@ -636,6 +636,10 @@ export class Image {
636636
return subtract(this, other, options);
637637
}
638638

639+
public add(other: Image): Image {
640+
return add(this, other);
641+
}
642+
639643
// COMPUTE
640644

641645
public histogram(options?: HistogramOptions): Uint32Array {

src/compare/__tests__/add.test.ts

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import { add } from '../add';
2+
3+
test('add image to itself', () => {
4+
const image = testUtils.createRgbImage([[5, 5, 5, 10, 10, 10, 15, 15, 15]]);
5+
const other = image;
6+
expect(add(image, other)).toMatchImageData([
7+
[10, 10, 10, 20, 20, 20, 30, 30, 30],
8+
]);
9+
});
10+
11+
test('add two different images', () => {
12+
const image = testUtils.createRgbImage([[5, 5, 5, 10, 10, 10, 15, 15, 15]]);
13+
const other = testUtils.createRgbImage([[0, 0, 0, 20, 20, 20, 15, 15, 15]]);
14+
expect(add(image, other)).toMatchImageData([
15+
[5, 5, 5, 30, 30, 30, 30, 30, 30],
16+
]);
17+
});
18+
19+
test('add two different images whose sum exceeds the maxValue', () => {
20+
const image = testUtils.createRgbImage([
21+
[200, 200, 5, 10, 10, 10, 15, 15, 15],
22+
]);
23+
const other = testUtils.createRgbImage([
24+
[240, 200, 20, 20, 250, 20, 15, 15, 15],
25+
]);
26+
expect(image.add(other)).toMatchImageData([
27+
[255, 255, 25, 30, 255, 30, 30, 30, 30],
28+
]);
29+
});
30+
31+
test('different bitDepth should throw', () => {
32+
const image = testUtils.createRgbImage([[5, 5, 5, 10, 10, 10, 15, 15, 15]], {
33+
bitDepth: 16,
34+
});
35+
const other = testUtils.createRgbImage([[0, 0, 0, 20, 20, 20, 15, 15, 15]], {
36+
bitDepth: 8,
37+
});
38+
expect(() => {
39+
return add(image, other);
40+
}).toThrow('both images must have the same alpha and bitDepth');
41+
});
42+
43+
test('different size images should throw', () => {
44+
const image = testUtils.createRgbImage([[5, 5, 5, 10, 10, 10, 15, 15, 15]]);
45+
const other = testUtils.createRgbImage([[5, 5, 5, 10, 10, 10]]);
46+
expect(() => {
47+
add(image, other);
48+
}).toThrow(`both images must have the same size`);
49+
});
50+
51+
test('different number of channels should throw', () => {
52+
const image = testUtils.createGreyImage([[5, 10, 15]]);
53+
const other = testUtils.createRgbImage([[1, 1, 1, 5, 5, 5, 10, 10, 10]]);
54+
expect(() => {
55+
image.subtract(other);
56+
}).toThrow(`both images must have the same number of channels`);
57+
});
58+
59+
test('different number of channels should throw', () => {
60+
const image = testUtils.createGreyImage([[5, 10, 15]]);
61+
const other = testUtils.createRgbImage([[1, 1, 1, 5, 5, 5, 10, 10, 10]]);
62+
expect(() => {
63+
image.subtract(other);
64+
}).toThrow(`both images must have the same number of channels`);
65+
});

src/compare/add.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { Image } from '..';
2+
import { getClamp } from '../utils/clamp';
3+
import checkProcessable from '../utils/validators/checkProcessable';
4+
import { validateForComparison } from '../utils/validators/validators';
5+
/**
6+
*
7+
* Calculate a new image that is the sum between the current image and the otherImage.
8+
* @param image - Image to which to add.
9+
* @param otherImage - Image to add.
10+
* @returns The summed image.
11+
*/
12+
export function add(image: Image, otherImage: Image): Image {
13+
if (image instanceof Image) {
14+
checkProcessable(image, {
15+
bitDepth: [8, 16],
16+
components: [1, 3],
17+
alpha: false,
18+
});
19+
}
20+
21+
validateForComparison(image, otherImage);
22+
23+
const newImage = image.clone();
24+
const clamp = getClamp(image);
25+
for (let index = 0; index < image.size; index++) {
26+
for (let channel = 0; channel < image.channels; channel++) {
27+
const value =
28+
image.getValueByIndex(index, channel) +
29+
otherImage.getValueByIndex(index, channel);
30+
newImage.setValueByIndex(index, channel, clamp(value));
31+
}
32+
}
33+
return newImage;
34+
}

src/compare/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ export * from './computePsnr';
33
export * from './computeRmse';
44
export * from './computeSsim';
55
export * from './subtract';
6+
export * from './add';

0 commit comments

Comments
 (0)