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

Commit b91cb35

Browse files
committed
feat: add setBlendedVisiblePixel to drawLineOnImage
1 parent ec04a57 commit b91cb35

File tree

2 files changed

+69
-1
lines changed

2 files changed

+69
-1
lines changed

src/draw/drawLineOnImage.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { Image } from '../Image';
44
import { Point } from '../utils/geometry/points';
55
import { getDefaultColor } from '../utils/getDefaultColor';
66
import { getOutputImage } from '../utils/getOutputImage';
7+
import { setBlendedVisiblePixel } from '../utils/setBlendedVisiblePixel';
78
import checkProcessable from '../utils/validators/checkProcessable';
89
import { validateColor } from '../utils/validators/validators';
910

@@ -56,7 +57,7 @@ export function drawLineOnImage(
5657
Math.round(origin.column + to.column),
5758
Math.round(origin.row + to.row),
5859
(column: number, row: number) => {
59-
newImage.setVisiblePixel(column, row, color);
60+
setBlendedVisiblePixel(newImage, column, row, { color });
6061
},
6162
);
6263
return newImage;

src/utils/setBlendedVisiblePixel.ts

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import { Image } from '../Image';
2+
import { Mask } from '../Mask';
3+
4+
import { getDefaultColor } from './getDefaultColor';
5+
import { assert } from './validators/assert';
6+
7+
export interface SetBlendedVisiblePixelOptions {
8+
/**
9+
* Color with which to blend the image pixel.
10+
* @default `'Opaque black'`.
11+
*/
12+
color?: number[];
13+
}
14+
15+
/**
16+
* Blend the given pixel with the pixel at the specified location in the image if the pixel is in image's bounds.
17+
* @param image - The image with which to blend.
18+
* @param column - Column of the target pixel.
19+
* @param row - Row of the target pixel.
20+
* @param options - Set blended pixel options.
21+
*/
22+
export function setBlendedVisiblePixel(
23+
image: Image | Mask,
24+
column: number,
25+
row: number,
26+
options: SetBlendedVisiblePixelOptions = {},
27+
) {
28+
const { color = getDefaultColor(image) } = options;
29+
30+
if (!image.alpha) {
31+
image.setVisiblePixel(column, row, color);
32+
} else {
33+
assert(image instanceof Image);
34+
35+
const sourceAlpha = color.at(-1) as number;
36+
37+
if (sourceAlpha === image.maxValue) {
38+
image.setVisiblePixel(column, row, color);
39+
return;
40+
}
41+
42+
const targetAlpha = image.getValue(column, row, image.channels - 1);
43+
44+
const newAlpha =
45+
sourceAlpha + targetAlpha * (1 - sourceAlpha / image.maxValue);
46+
if (column >= 0 && column < image.width && row >= 0 && row < image.height) {
47+
image.setValue(column, row, image.channels - 1, newAlpha);
48+
}
49+
for (let component = 0; component < image.components; component++) {
50+
const sourceComponent = color[component];
51+
const targetComponent = image.getValue(column, row, component);
52+
53+
const newComponent =
54+
(sourceComponent * sourceAlpha +
55+
targetComponent * targetAlpha * (1 - sourceAlpha / image.maxValue)) /
56+
newAlpha;
57+
if (
58+
column >= 0 &&
59+
column < image.width &&
60+
row >= 0 &&
61+
row < image.height
62+
) {
63+
image.setValue(column, row, component, newComponent);
64+
}
65+
}
66+
}
67+
}

0 commit comments

Comments
 (0)