UNPKG

image-js

Version:

Image processing and manipulation in JavaScript

75 lines 3.59 kB
import { circle } from 'bresenham-zingl'; import { getDefaultColor } from '../utils/getDefaultColor.js'; import { getOutputImage } from '../utils/getOutputImage.js'; import { setBlendedVisiblePixel } from '../utils/setBlendedVisiblePixel.js'; import checkProcessable from '../utils/validators/checkProcessable.js'; import { validateColor } from '../utils/validators/validators.js'; import { roundPoint } from './utils/roundPoint.js'; /** * Draw a circle defined by center and radius. * @param image - Image to process. * @param center - Circle center point. * @param radius - Circle radius. * @param options - Draw circle options. * @returns The original drawn image. */ export function drawCircleOnImage(image, center, radius, options = {}) { const newImage = getOutputImage(image, options, { clone: true }); const { strokeColor = getDefaultColor(newImage), fillColor } = options; validateColor(strokeColor, newImage); checkProcessable(newImage, { bitDepth: [8, 16], }); if (radius < 0) { throw new RangeError('circle radius must be positive'); } center = roundPoint(center); radius = Math.round(radius); if (radius === 0) { setBlendedVisiblePixel(newImage, center.column, center.row, strokeColor); return newImage; } if (!fillColor) { circle(center.column, center.row, radius, (column, row) => { setBlendedVisiblePixel(newImage, column, row, strokeColor); }); } else { if (radius === 1) { setBlendedVisiblePixel(newImage, center.column, center.row, fillColor); } //Starting points for the top and bottom row of the circle. let prevRow = center.row + radius; let index = 0; circle(center.column, center.row, radius, (column, row) => { setBlendedVisiblePixel(newImage, column, row, strokeColor); // Filling the first line of the circle. if (index === 0) { newImage.drawLine({ row, column: column - 1 }, { row, column: center.column - (column - center.column - 1), }, { strokeColor: fillColor, out: newImage }); } // The algorithm used is Bresenham's circle algorithm (@link https://www.geeksforgeeks.org/bresenhams-circle-drawing-algorithm/) to find points that constitute the circle outline. However, in this algorithm The circle is divided in 4 parts instead of 8: top, right, bottom and left. // The algorithm draws a point per quadrant until the circle is complete. // We use bottom (index % 4 === 1, quadrant 2) point of the outline to fill the circle with color. // Filling half of the circle. if (index % 4 === 1 && prevRow !== row) { // For quadrant 2, column < center.column newImage.drawLine({ row, column: column + 1 }, { row, column: center.column - (column - center.column + 1), }, { strokeColor: fillColor, out: newImage }); prevRow = row; // Filling top half of the circle. newImage.drawLine({ row: center.row - (row - center.row), column: column + 1 }, { row: center.row - (row - center.row), column: center.column - (column - center.column + 1), }, { strokeColor: fillColor, out: newImage }); } index++; }); } return newImage; } //# sourceMappingURL=drawCircleOnImage.js.map