55 lines
2.0 KiB
JavaScript
55 lines
2.0 KiB
JavaScript
|
|
function cropX(imageData, { left = 0, right = 0 }) {
|
||
|
|
const { data, width, height } = imageData;
|
||
|
|
const dataLength = data.length;
|
||
|
|
const newWidth = width - left - right;
|
||
|
|
const rowLength = width * 4;
|
||
|
|
const newRowLength = newWidth * 4;
|
||
|
|
const leftCrop = left * 4;
|
||
|
|
const newData = [];
|
||
|
|
// loop through each row
|
||
|
|
for (let x = 0; x < dataLength; x += rowLength) {
|
||
|
|
const newRowStart = x + leftCrop;
|
||
|
|
const newRowEnd = newRowStart + newRowLength;
|
||
|
|
for (let i = newRowStart; i < newRowEnd; i += 4) {
|
||
|
|
newData.push(data[i], data[i + 1], data[i + 2], data[i + 3]);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return { data: newData, height, width: newWidth };
|
||
|
|
}
|
||
|
|
function cropY(imageData, { top = 0, bottom = 0 }) {
|
||
|
|
const { data, width, height } = imageData;
|
||
|
|
const rowLength = width * 4;
|
||
|
|
const topIndex = top * rowLength;
|
||
|
|
const bottomIndex = bottom * rowLength;
|
||
|
|
const newHeight = height - top - bottom;
|
||
|
|
const newDataEnd = data.length - bottomIndex;
|
||
|
|
const newData = [];
|
||
|
|
// save each index within the cropped area (avoid .slice() for performance)
|
||
|
|
for (let i = topIndex; i < newDataEnd; i++) {
|
||
|
|
newData.push(data[i]);
|
||
|
|
}
|
||
|
|
return { data: newData, height: newHeight, width };
|
||
|
|
}
|
||
|
|
function toNumber(options) {
|
||
|
|
return Object.fromEntries(Object.entries(options).map(([key, value]) => [key, Number(value || 0)]));
|
||
|
|
}
|
||
|
|
export default function cropImageData(imageData, cropOptions) {
|
||
|
|
const { top, right, bottom, left } = toNumber(cropOptions);
|
||
|
|
if (imageData.height < top + bottom || imageData.width < left + right) {
|
||
|
|
return new ImageData(1, 1);
|
||
|
|
}
|
||
|
|
let newImageData = {
|
||
|
|
data: imageData.data,
|
||
|
|
width: imageData.width,
|
||
|
|
height: imageData.height,
|
||
|
|
};
|
||
|
|
if (top || bottom) {
|
||
|
|
newImageData = cropY(newImageData, { top, bottom });
|
||
|
|
}
|
||
|
|
if (left || right) {
|
||
|
|
newImageData = cropX(newImageData, { left, right });
|
||
|
|
}
|
||
|
|
const { data, height, width } = newImageData;
|
||
|
|
return new ImageData(Uint8ClampedArray.from(data), width, height);
|
||
|
|
}
|