image-js
Version:
Image processing and manipulation in JavaScript
105 lines • 4.01 kB
JavaScript
import { xMedian } from 'ml-spectra-processing';
import { getOutputImage } from '../utils/getOutputImage.js';
import { assertUnreachable } from '../utils/validators/assert.js';
/**
* Function to pixelate an image.
* @param image - Image to be pixelated.
* @param options - PixelateOptions.
* @returns Pixelated Image.
*/
export function pixelate(image, options) {
const { cellSize, algorithm = 'center' } = options;
if (!Number.isInteger(cellSize)) {
throw new TypeError('cellSize must be an integer');
}
if (cellSize < 2) {
throw new RangeError('cellSize must be greater than 1');
}
const newImage = getOutputImage(image, options);
const getCellValue = getCellValueFunction(algorithm);
for (let channel = 0; channel < image.channels; channel++) {
for (let column = 0; column < image.width; column += cellSize) {
for (let row = 0; row < image.height; row += cellSize) {
const currentCellWidth = Math.min(cellSize, image.width - column);
const currentCellHeight = Math.min(cellSize, image.height - row);
const value = getCellValue(image, channel, {
width: currentCellWidth,
height: currentCellHeight,
origin: { column, row },
});
for (let newColumn = column; newColumn < column + currentCellWidth; newColumn++) {
for (let newRow = row; newRow < row + currentCellHeight; newRow++) {
newImage.setValue(newColumn, newRow, channel, value);
}
}
}
}
}
return newImage;
}
/**
* Computes the center value for the current sector
* @param image - image used for the algorithm
* @param channel - image channel toto find center value of
* @param options - GetValueOptions
* @returns center value
*/
function getCellCenter(image, channel, options) {
const center = {
column: Math.floor((options.origin.column + options.origin.column + options.width - 1) / 2),
row: Math.floor((options.origin.row + options.origin.row + options.height - 1) / 2),
};
const value = image.getValue(center.column, center.row, channel);
return value;
}
/**
* Computes mean value for the current sector
* @param image - image used for algorithm
* @param channel - current channel of an image
* @param options - GetValueOptions
* @returns mean value
*/
function getCellMean(image, channel, options) {
let sum = 0;
for (let column = options.origin.column; column < options.origin.column + options.width; column++) {
for (let row = options.origin.row; row < options.origin.row + options.height; row++) {
sum += image.getValue(column, row, channel);
}
}
return Math.round(sum / (options.width * options.height));
}
/**
* Computes a median value for the current sector
* @param image - image used algorithm
* @param channel - current channel of an image
* @param options - GetValueOptions
* @returns median value
*/
function getCellMedian(image, channel, options) {
const array = [];
for (let column = options.origin.column; column < options.origin.column + options.width; column++) {
for (let row = options.origin.row; row < options.origin.row + options.height; row++) {
array.push(image.getValue(column, row, channel));
}
}
return xMedian(array);
}
/**
* Chooses which algorithm to use for pixelization and returns a function to use for computation
* @param algorithm - string with the name of an algorithm
* @returns function
*/
function getCellValueFunction(algorithm) {
switch (algorithm) {
case 'mean':
return getCellMean;
case 'median':
return getCellMedian;
case 'center':
return getCellCenter;
default:
assertUnreachable(algorithm);
break;
}
}
//# sourceMappingURL=pixelate.js.map