使用canvas.toDataURL()导出png时禁用抗锯齿

时间:2018-08-14 19:00:16

标签: javascript canvas fabricjs

我有一块画布,可以使用fabric.js绘制一些形状。然后,我填充这些形状,并使用context.drawImage()将它们绘制在另一个画布上,并使用canvas.toDataURL()导出为png。

我已经关闭了我绘制到的画布以及导出到png的画布的enableRetinaScaling和imageSmoothingEnabled。

我得到的png在形状的边缘具有不同的颜色像素,并且似乎抗锯齿或模糊。有没有一种方法可以禁用此功能,并让每个像素的边框周围都具有相同的颜色?我知道这将导致边缘不光滑,这很好。

const canvas = document.getElementById('canvas');
let ctx = canvas.getContext('2d');
ctx.imageSmoothingEnabled = false;

const drawingCanvas = new fabric.Canvas(canvas, {
  width: 150,
  height: 150,
  backgroundColor: 'transparent',
  selection: false,
  enableRetinaScaling: false,
  imageSmoothingEnabled: false,
});

let polygon = new fabric.Polygon([
  {  x: 50,  y: 100 }, 
  {  x: 70,  y: 10 }, 
  {  x: 90,  y: 100 }, 
], {
  stroke: 'green',
  fill: 'green',
  selectable: false,
  perPixelTargetFind: true,
  hoverCursor: 'cursor'
});

drawingCanvas.add(polygon);
drawingCanvas.renderAll();

link = document.getElementById('download');
link.setAttribute("href", canvas.toDataURL());
link.setAttribute("download", "example.png");
<body>
  <a id="download"><button>Download</button></a>
  <canvas id="canvas" style="border: solid red 1px" />
</body>

<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.3.5/fabric.js"></script>

png的特写,显示不同的像素阴影 A close up of the png, showing different pixel shades

2 个答案:

答案 0 :(得分:0)

这似乎是由用于在画布上绘制线条的算法引起的,我认为我们没有办法更改它,唯一的选择是使用其他算法自己绘制所有内容,例如:
https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm

在您的示例中,您正在使用fabric.js,但是这种情况也以最基本的线条绘制形式发生,这是and示例:

const canvas = document.getElementById('canvas');
canvas.width = canvas.height = 50;
let ctx = canvas.getContext('2d');
ctx.imageSmoothingEnabled = false
ctx.mozImageSmoothingEnabled = false;

ctx.translate(0.5, 0.5)
ctx.beginPath();
ctx.moveTo(0, 10);
ctx.lineTo(10, 10);
ctx.lineTo(30, 30);
ctx.lineTo(40, 10);
ctx.stroke();
ctx.closePath();

link = document.getElementById('download');
link.setAttribute("href", canvas.toDataURL());
link.setAttribute("download", "example.png");
<body>
  <a id="download"><button>Download</button></a><br>
  <canvas id="canvas" style="border: solid red 1px" />
</body>

答案 1 :(得分:0)

这是一个可能的解决方案。 您不能从画布上删除别名,至少不在规范中,并且不受您的控制。

但是您可以在导出像素后对其进行操作。

输出是:

enter image description here

但不适用于重叠的形状。

const canvas = document.getElementById('canvas');
let ctx = canvas.getContext('2d');
ctx.imageSmoothingEnabled = false;

const drawingCanvas = new fabric.Canvas(canvas, {
  width: 150,
  height: 150,
  backgroundColor: 'transparent',
  selection: false,
  enableRetinaScaling: false,
  imageSmoothingEnabled: false,
});

let polygon = new fabric.Polygon([
  {  x: 50,  y: 100 }, 
  {  x: 70,  y: 10 }, 
  {  x: 90,  y: 100 }, 
], {
  stroke: 'green',
  fill: 'green',
  selectable: false,
  perPixelTargetFind: true,
  hoverCursor: 'cursor'
});

drawingCanvas.add(polygon);
drawingCanvas.renderAll();

function myNewImage() {
  const _canvas = document.createElement('canvas');
  const pixels = drawingCanvas.lowerCanvasEl;
  _canvas.width = pixels.width;
  _canvas.height = pixels.height;
  const ctx = _canvas.getContext('2d');
  ctx.drawImage(pixels, 0, 0);
  const data = ctx.getImageData(0, 0, _canvas.width, _canvas.height);
  const pixelArray = data.data;
  for (let i = 3; i < pixelArray.length; i += 4) {
    if (pixelArray[i] < 128) {
      pixelArray[i] = 0;
    } else {
      pixelArray[i] = 255;
    }
  }
  ctx.putImageData(data, 0, 0);
  return _canvas.toDataURL('image/png');
}

link = document.getElementById('download');
link.setAttribute("href", myNewImage());
link.setAttribute("download", "example.png");
<body>
  <a id="download"><button>Download</button></a>
  <canvas id="canvas" style="border: solid red 1px" />
</body>

<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.3.5/fabric.js"></script>