Как убрать прозрачные пиксели, которые окружают Canvas в JavaScript

В некоторых ситуациях, когда вы работаете с Canvas, используя фреймворк или нет, вы не сможете предоставить фиксированный размер холста, поскольку он может автоматически генерироваться библиотекой, и теперь ваша ответственность заключается в том, что с ним делать. Проблема этого подхода заключается в том, что иногда эти холсты будут содержать огромные поля вокруг содержимого, в основном пустые пространства, которые, вероятно, никому не нужны на изображении, поскольку это значительно увеличивает размер (визуальный и размер файла).

Если вы хотите быстро и легко решить эту проблему, выполните следующие действия. trimCanvas функция, которая была написана Реми Шарп, поможет вам решить эту проблемную функцию, которая может понадобиться многим разработчикам когда-нибудь при работе с Canvas:

// MIT http://rem.mit-license.org
function trimCanvas(c) {
var ctx = c.getContext('2d'),
copy = document.createElement('canvas').getContext('2d'),
pixels = ctx.getImageData(0, 0, c.width, c.height),
l = pixels.data.length,
i,
bound = {
top: null,
left: null,
right: null,
bottom: null
},
x, y;
// Iterate over every pixel to find the highest
// and where it ends on every axis ()
for (i = 0; i < l; i += 4) {
if (pixels.data[i + 3] !== 0) {
x = (i / 4) % c.width;
y = ~~((i / 4) / c.width);
if (bound.top === null) {
bound.top = y;
}
if (bound.left === null) {
bound.left = x;
} else if (x < bound.left) {
bound.left = x;
}
if (bound.right === null) {
bound.right = x;
} else if (bound.right < x) {
bound.right = x;
}
if (bound.bottom === null) {
bound.bottom = y;
} else if (bound.bottom < y) {
bound.bottom = y;
}
}
}
// Calculate the height and width of the content
var trimHeight = bound.bottom - bound.top,
trimWidth = bound.right - bound.left,
trimmed = ctx.getImageData(bound.left, bound.top, trimWidth, trimHeight);
copy.canvas.width = trimWidth;
copy.canvas.height = trimHeight;
copy.putImageData(trimmed, 0, 0);
// Return trimmed canvas
return copy.canvas;
}

Логика функции хотя и не проста в написании, но ее легко понять. Функция ожидает в качестве первого аргумента объект холста, а не контекст, так как сценарий должен сделать копию холста, чтобы создать новый с его содержимым, но без перезаписи содержимого оригинала. Затем все пиксели сохраняются в массиве, который будет повторяться с циклом for, чтобы найти наивысшие граничные точки на изображении, чтобы упорядочить его (в основном строит объект с координатами, в которых хранятся ваши данные холста). После сохранения точек (сверху, слева, снизу и справа) они используются для вырезания исходных данных холста и добавления нового содержимого в созданную копию. Эта копия возвращается функцией, что означает, что возвращается другой экземпляр Canvas.

пример

В этом примере мы покажем вам, как обрезать крупье, который будет нарисован внутри холста 400x400, с помощью следующего кода:


var canvas = document.getElementById("stickman");
context = canvas.getContext("2d"); // get Canvas Context object
context.beginPath();
context.fillStyle = "bisque"; // #ffe4c4
context.arc(200, 50, 30, 0, Math.PI * 2, true); // draw circle for head
// (x,y) center, radius, start angle, end angle, anticlockwise
context.fill();
context.beginPath();
context.strokeStyle = "red"; // color
context.lineWidth = 3;
context.arc(200, 50, 20, 0, Math.PI, false); // draw semicircle for smiling
context.stroke();
// eyes
context.beginPath();
context.fillStyle = "green"; // color
context.arc(190, 45, 3, 0, Math.PI * 2, true); // draw left eye
context.fill();
context.arc(210, 45, 3, 0, Math.PI * 2, true); // draw right eye
context.fill();
// body
context.beginPath();
context.moveTo(200, 80);
context.lineTo(200, 180);
context.strokeStyle = "navy";
context.stroke();
// arms
context.beginPath();
context.strokeStyle = "#0000ff"; // blue
context.moveTo(200, 80);
context.lineTo(150, 130);
context.moveTo(200, 80);
context.lineTo(250, 130);
context.stroke();
// legs
context.beginPath();
context.strokeStyle = "orange";
context.moveTo(200, 180);
context.lineTo(150, 280);
context.moveTo(200, 180);
context.lineTo(250, 280);
context.stroke();

Предыдущий код сгенерирует крупье на холсте, если он будет экспортирован, результат изображения png будет следующим:

Пример обрезки прозрачных пикселей вокруг холста

Как вы можете видеть, мы хотим иметь только stickman, но наш холст больше, чем нарисованный путь, поэтому есть много места, которое мы можем просто выбросить с помощью функции trimCanvas, просто выполнив:

// Crop and obtain the new canvas
var trimmedCanvas = trimCanvas(canvas);
// data:image/png;base64,iVBORw0KGgoAAAANSUhE..........XTklIOUbk4AAAAAElFTkSuQmCC
console.log(trimmedCanvas.toDataURL());

Если вы показываете предварительный просмотр сгенерированной строки base64, которая содержит изображение, вывод будет теперь только нашим крупье как trimCanvas Функция убрала пустые пиксели, которые окружают оригинальный холст:

Удалить прозрачные пиксели из примера холста

Удачного кодирования!

Ссылка на основную публикацию
Adblock
detector