Как выборочно убрать пустую область с картинки с помощью JavaScript?
Есть png изображение с пустой областью по краям (на скриншоте пустая область - это клеточки)
Можно ли как-то сделать так, чтобы область сверху и снизу обрезалась, а по краям осталась?
Пока есть вариант пробегаться по каждому пикселю, если весь ряд пустой, то удаляем. Но может есть более простой способ?
Ответы (1 шт):
Вот пример кода, к сожалению сниппет создать не удалось, но код работает относительно быстро, за счет метода массива some. Строка которая появилась сверху это новое изображение на канвасе нарисованное поверх оригинального (600x600 со словом "пример" в центре).
loadImageзагужает изображениеgetDataполучает пиксельные данные (по четыре байта на пискельrgba) следует учесть что иногда данные изображения получить нельзя из-за того что оно будет находится в другом домене можно попробовать установить аттрибутimg.setAttribute('crossOrigin', '')в строке
line = data.data.slice(i, i + blockSize)мы вырезаем линию из изображения(line.some(byte => byte !== 0))проверяет что она не полностью пуста (иначе ни данных о цвете ни о прозрачности - все нули).зная начальную и конечные линии "непустого" изображения можем вырезать его
ctx.getImageData(0, top, width , newHeight);.и отрисовать новое изображение
ctx.putImageData(trimmedImage, 0, 0)
function loadImage (imageUrl){
return new Promise((resolve, reject) => {
const img = new Image();
img.onload = function() {
resolve({img, width: this.width, height : this.height})
}
img.src = imageUrl;
})
}
function getData(ctx, width, height){
try {
return ctx.getImageData(0, 0, width, height);
} catch(e) {
return null; // ошибка получения данных
}
}
function trimTransparent(ctx, width, height){
const blockSize = width * 4
const data = getData(ctx, width, height)
if (!data) return null
const length = data.data.length;
const filledLines = [];
let i = 0;
let lineNumber = 0
while (i < length) {
lineNumber += 1
line = data.data.slice(i, i + blockSize)
if (line.some(byte => byte !== 0)) {
filledLines.push(lineNumber)
}
i += blockSize
}
const top = filledLines.shift()
const newHeight = filledLines.pop() - top
return ctx.getImageData(0, top, width , newHeight);
}
async function trimImage(imageUrl){
const {img, width, height} = await loadImage(imageUrl)
// можно создавать временный канвас вне DOM
const canvas = document.querySelector('canvas');
canvas.width = width;
canvas.height = height;
const ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0, width, height);
const trimmedImage = trimTransparent(ctx, width, height)
if (trimmedImage){
ctx.putImageData(trimmedImage, 0, 0)
}
}
trimImage("example.png")
<canvas></canvas>


