Я играю с <canvas>
элементом, рисую линии и тому подобное.
Я заметил, что мои диагональные линии сглажены. Я бы предпочел неровный вид того, что я делаю - есть ли способ отключить эту функцию?
javascript
html
canvas
antialiasing
Blorgbeard отсутствует
источник
источник
Ответы:
Для изображений есть сейчас .
context.imageSmoothingEnabled
= false
Однако нет ничего, что явно управляло бы рисованием линий. Возможно, вам придется рисовать свои собственные линии ( сложный способ ), используя
getImageData
иputImageData
.источник
putImageData
но он все еще чертовски сглаживает соседние пиксели.Проведите свои
1-pixel
линии в координатах вродеctx.lineTo(10.5, 10.5)
. Проведение линии в один пиксель над точкой(10, 10)
означает, что этот1
пиксель в этой позиции простирается от9.5
до10.5
результате чего на холсте рисуются две линии.Хороший трюк, позволяющий не всегда добавлять
0.5
к фактической координате, которую вы хотите нарисовать, если у вас много линий в один пиксель, -ctx.translate(0.5, 0.5)
это вначале весь ваш холст.источник
ctx.translate(0.5,0.5)
не работает. on FF39.0Это можно сделать в Mozilla Firefox. Добавьте это в свой код:
contextXYZ.mozImageSmoothingEnabled = false;
В Opera в настоящее время это запрос функции, но, надеюсь, он скоро будет добавлен.
источник
"whether pattern fills and the drawImage() method will attempt to smooth images if their pixels don't line up exactly with the display, when scaling images up"
Это должно быть антиалиас векторная графика
Сглаживание требуется для правильного построения векторной графики, которая использует нецелочисленные координаты (0,4, 0,4), что делают все, кроме очень немногих клиентов.
Если заданы нецелочисленные координаты, у холста есть два варианта:
Более поздняя стратегия будет работать для статической графики, хотя для небольшой графики (круг с радиусом 2) кривые будут показывать четкие шаги, а не плавную кривую.
Настоящая проблема заключается в том, что графика переводится (перемещается) - скачки между одним пикселем и другим (1.6 => 2, 1.4 => 1) означают, что начало координат фигуры может перескакивать относительно родительского контейнера (постоянно смещается 1 пиксель вверх / вниз и влево / вправо).
Несколько советов
Совет №1 : вы можете смягчить (или усилить) сглаживание, масштабируя холст (скажем, по x), а затем самостоятельно применив обратный масштаб (1 / x) к геометрии (не используя холст).
Сравнить (без масштабирования):
с (масштаб холста: 0,75; ручной масштаб: 1,33):
и (масштаб холста: 1,33; ручной масштаб: 0,75):
Совет №2 : Если вы действительно хотите получить неровный вид, попробуйте нарисовать каждую форму несколько раз (без стирания). С каждым рисованием пиксели сглаживания становятся темнее.
Сравните. После нанесения один раз:
После трехкратного рисования:
источник
Я бы нарисовал все, используя собственный линейный алгоритм, такой как линейный алгоритм Брезенхема. Посмотрите эту реализацию javascript: http://members.chello.at/easyfilter/canvas.html
Думаю, это точно решит ваши проблемы.
источник
setPixel(x, y)
; Я использовал принятый ответ здесь: stackoverflow.com/questions/4899799/…Хочу добавить, что у меня возникли проблемы при уменьшении размера изображения и рисовании на холсте, оно все еще использовало сглаживание, хотя оно не использовалось при масштабировании.
Я решил использовать это:
function setpixelated(context){ context['imageSmoothingEnabled'] = false; /* standard */ context['mozImageSmoothingEnabled'] = false; /* Firefox */ context['oImageSmoothingEnabled'] = false; /* Opera */ context['webkitImageSmoothingEnabled'] = false; /* Safari */ context['msImageSmoothingEnabled'] = false; /* IE */ }
Вы можете использовать эту функцию так:
var canvas = document.getElementById('mycanvas') setpixelated(canvas.getContext('2d'))
Может это кому пригодится.
источник
ctx.translate(0.5, 0.5); ctx.lineWidth = .5;
С помощью этой комбинации я могу нарисовать красивые тонкие линии в 1 пиксель.
источник
Обратите внимание на очень ограниченный трюк. Если вы хотите создать двухцветное изображение, вы можете нарисовать любую фигуру цветом # 010101 на фоне с цветом # 000000. Как только это будет сделано, вы можете протестировать каждый пиксель в imageData.data [] и установить в 0xFF любое значение, отличное от 0x00:
imageData = context2d.getImageData (0, 0, g.width, g.height); for (i = 0; i != imageData.data.length; i ++) { if (imageData.data[i] != 0x00) imageData.data[i] = 0xFF; } context2d.putImageData (imageData, 0, 0);
В результате будет черно-белое изображение без антиалиасинга. Это не будет идеально, поскольку будет иметь место некоторое сглаживание, но это сглаживание будет очень ограниченным, так как цвет формы очень похож на цвет фона.
источник
Для тех, кто все еще ищет ответы. вот мое решение.
Предполагается, что изображение - 1 канал серого цвета. Я просто установил порог после ctx.stroke ().
ctx.beginPath(); ctx.moveTo(some_x, some_y); ctx.lineTo(some_x, some_y); ... ctx.closePath(); ctx.fill(); ctx.stroke(); let image = ctx.getImageData(0, 0, ctx.canvas.width, ctx.canvas.height) for(let x=0; x < ctx.canvas.width; x++) { for(let y=0; y < ctx.canvas.height; y++) { if(image.data[x*image.height + y] < 128) { image.data[x*image.height + y] = 0; } else { image.data[x*image.height + y] = 255; } } }
если ваш канал изображения 3 или 4. вам нужно изменить индекс массива, например
источник
Всего две заметки об ответе StashOfCode:
Лучше сделать так:
Обведите и залейте
#FFFFFF
, затем сделайте следующее:imageData.data[i] = (imageData.data[i] >> 7) * 0xFF
Это решает проблему для линий шириной 1 пиксель.
Помимо этого, решение StashOfCode идеально, потому что оно не требует написания ваших собственных функций растеризации (подумайте не только о линиях, но и о кривых Безье, дугах окружности, заполненных многоугольниках с отверстиями и т. Д.)
источник
Вот базовая реализация алгоритма Брезенхэма на JavaScript. Он основан на версии целочисленной арифметики, описанной в этой статье в Википедии: https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm
function range(f=0, l) { var list = []; const lower = Math.min(f, l); const higher = Math.max(f, l); for (var i = lower; i <= higher; i++) { list.push(i); } return list; } //Don't ask me. //https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm function bresenhamLinePoints(start, end) { let points = []; if(start.x === end.x) { return range(f=start.y, l=end.y) .map(yIdx => { return {x: start.x, y: yIdx}; }); } else if (start.y === end.y) { return range(f=start.x, l=end.x) .map(xIdx => { return {x: xIdx, y: start.y}; }); } let dx = Math.abs(end.x - start.x); let sx = start.x < end.x ? 1 : -1; let dy = -1*Math.abs(end.y - start.y); let sy = start.y < end.y ? 1 : - 1; let err = dx + dy; let currX = start.x; let currY = start.y; while(true) { points.push({x: currX, y: currY}); if(currX === end.x && currY === end.y) break; let e2 = 2*err; if (e2 >= dy) { err += dy; currX += sx; } if(e2 <= dx) { err += dx; currY += sy; } } return points; }
источник
Попробуйте что-нибудь вроде
canvas { image-rendering: pixelated; }
.Это может не сработать, если вы пытаетесь сделать не сглаженным только одну строку.
const canvas = document.querySelector("canvas"); const ctx = canvas.getContext("2d"); ctx.fillRect(4, 4, 2, 2);
canvas { image-rendering: pixelated; width: 100px; height: 100px; /* Scale 10x */ }
<html> <head></head> <body> <canvas width="10" height="10">Canvas unsupported</canvas> </body> </html>
Однако я не тестировал это во многих браузерах.
источник