Skip to content

Commit

Permalink
feat: add setBlendedVisiblePixel to drawLineOnImage
Browse files Browse the repository at this point in the history
  • Loading branch information
EscapedGibbon committed Sep 25, 2024
1 parent ec04a57 commit b91cb35
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 1 deletion.
3 changes: 2 additions & 1 deletion src/draw/drawLineOnImage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Image } from '../Image';
import { Point } from '../utils/geometry/points';
import { getDefaultColor } from '../utils/getDefaultColor';
import { getOutputImage } from '../utils/getOutputImage';
import { setBlendedVisiblePixel } from '../utils/setBlendedVisiblePixel';
import checkProcessable from '../utils/validators/checkProcessable';
import { validateColor } from '../utils/validators/validators';

Expand Down Expand Up @@ -56,7 +57,7 @@ export function drawLineOnImage(
Math.round(origin.column + to.column),
Math.round(origin.row + to.row),
(column: number, row: number) => {
newImage.setVisiblePixel(column, row, color);
setBlendedVisiblePixel(newImage, column, row, { color });
},
);
return newImage;
Expand Down
67 changes: 67 additions & 0 deletions src/utils/setBlendedVisiblePixel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { Image } from '../Image';
import { Mask } from '../Mask';

import { getDefaultColor } from './getDefaultColor';
import { assert } from './validators/assert';

export interface SetBlendedVisiblePixelOptions {
/**
* Color with which to blend the image pixel.
* @default `'Opaque black'`.
*/
color?: number[];
}

/**
* Blend the given pixel with the pixel at the specified location in the image if the pixel is in image's bounds.
* @param image - The image with which to blend.
* @param column - Column of the target pixel.
* @param row - Row of the target pixel.
* @param options - Set blended pixel options.
*/
export function setBlendedVisiblePixel(
image: Image | Mask,
column: number,
row: number,
options: SetBlendedVisiblePixelOptions = {},
) {
const { color = getDefaultColor(image) } = options;

if (!image.alpha) {
image.setVisiblePixel(column, row, color);
} else {
assert(image instanceof Image);

const sourceAlpha = color.at(-1) as number;

if (sourceAlpha === image.maxValue) {
image.setVisiblePixel(column, row, color);
return;
}

const targetAlpha = image.getValue(column, row, image.channels - 1);

const newAlpha =
sourceAlpha + targetAlpha * (1 - sourceAlpha / image.maxValue);
if (column >= 0 && column < image.width && row >= 0 && row < image.height) {
image.setValue(column, row, image.channels - 1, newAlpha);
}
for (let component = 0; component < image.components; component++) {
const sourceComponent = color[component];
const targetComponent = image.getValue(column, row, component);

const newComponent =
(sourceComponent * sourceAlpha +
targetComponent * targetAlpha * (1 - sourceAlpha / image.maxValue)) /
newAlpha;
if (
column >= 0 &&
column < image.width &&
row >= 0 &&
row < image.height
) {
image.setValue(column, row, component, newComponent);
}
}
}
}

0 comments on commit b91cb35

Please sign in to comment.