image-js
Version:
Image processing and manipulation in JavaScript
63 lines • 2.75 kB
JavaScript
import { getClamp } from '../utils/clamp.js';
import { getOutputImage } from '../utils/getOutputImage.js';
import checkProcessable from '../utils/validators/checkProcessable.js';
import { validateChannels } from '../utils/validators/validators.js';
/**
* Level the image using the optional input and output value. The default options allow to increase the image's contrast.
* @param image - Image to process.
* @param options - Level options.
* @returns The levelled image.
*/
export function level(image, options = {}) {
const minMax = image.minMax();
let { inputMin = minMax.min, inputMax = minMax.max, outputMin = 0, outputMax = image.maxValue, gamma = 1, } = options;
const { channels = new Array(image.components).fill(0).map((value, index) => index), } = options;
validateChannels(channels, image);
checkProcessable(image, {
bitDepth: [8, 16],
});
const newImage = getOutputImage(image, options, { clone: true });
const clamp = getClamp(image);
inputMin = getValueArray(inputMin, image.channels);
inputMax = getValueArray(inputMax, image.channels);
outputMin = getValueArray(outputMin, image.channels);
outputMax = getValueArray(outputMax, image.channels);
gamma = getValueArray(gamma, image.channels);
for (let row = 0; row < image.height; row++) {
for (let column = 0; column < image.width; column++) {
for (const channel of channels) {
const currentValue = image.getValue(column, row, channel);
const clamped = Math.max(Math.min(currentValue, inputMax[channel]), inputMin[channel]);
let ratio = clamp((clamped - inputMin[channel]) /
(inputMax[channel] - inputMin[channel]));
if (Number.isNaN(ratio))
ratio = 0;
const result = clamp(ratio ** (1 / gamma[channel]) *
(outputMax[channel] - outputMin[channel]) +
outputMin[channel]);
newImage.setValue(column, row, channel, result);
}
}
}
return newImage;
}
/**
* Get an array with correct values for each channel to process.
* @param value - Number or array to transform to the final array.
* @param imageChannels - Number of channels processed in the level function.
* @returns Array of values for each channel.
*/
function getValueArray(value, imageChannels) {
if (Array.isArray(value)) {
if (value.length === imageChannels) {
return value;
}
else {
throw new RangeError('array length is not compatible with channel option');
}
}
else {
return new Array(imageChannels).fill(value);
}
}
//# sourceMappingURL=level.js.map