画布zoomIn / zoomOut:如何避免图像质量下降?

时间:2016-05-30 23:09:03

标签: image-processing canvas html5-canvas

我有这个用于缩放图像的代码。要zoomIn和zoomOut,请使用代码scalePicture(1.10, drawingContext);scalePicture(0.90, drawingContext);。我在离屏画布上执行该操作,然后将图像复制回原始屏幕。

我使用了屏幕外处理,因为浏览器通过使用双缓冲来优化图像操作。我仍然有一个问题,当我放大约400%然后zoomOut回到原始大小时,图像质量显着下降。

我不依赖于原始图像,因为用户可以执行许多操作,例如剪辑,裁剪,旋转,注释,我需要在原始图像上堆叠所有操作

任何人都可以提出一些建议/建议,以保持图像质量,同时不牺牲性能和质量。

    scalePicture : function(scalePercent, operatingCanvasContext) {
      var w = operatingCanvasContext.canvas.width,
           h = operatingCanvasContext.canvas.height,
           sw = w * scalePercent,
           sh = h * scalePercent,
           operatingCanvas = operatingCanvasContext.canvas;
       var canvasPic = new Image();
       operatingCanvasContext.save();
       canvasPic.src = operatingCanvas.toDataURL();
       operatingCanvasContext.clearRect (0,0, operatingCanvas.width, operatingCanvas.height);
       operatingCanvasContext.translate(operatingCanvas.width/2, operatingCanvas.height/2);
       canvasPic.onload = function () {
           operatingCanvasContext.drawImage(canvasPic, -sw/2 , -sh/2 , sw, sh);
           operatingCanvasContext.translate(-operatingCanvas.width/2, -operatingCanvas.height/2);
           operatingCanvasContext.restore();
       };
    }

1 个答案:

答案 0 :(得分:2)

画布是平局而忘记。如果不参考原始来源,就无法保留原始质量。

我建议重建记录的堆栈,但使用变换矩阵进行比例,旋转等的变化。然后将累积的矩阵应用于原始图像。这将保持最佳质量并提供一些性能提升(因为您只绘制最后和当前状态)。

类似于剪裁,计算和合并剪辑区域使用相同的矩阵,并在最终步骤中绘制原始图像之前应用剪辑。和文字等类似。

显示执行所有这些步骤的示例有点过于宽泛,但这里是一个示例,说明如何在原始图像上使用累积矩阵变换以保持最佳质量。您可以看到可以放大和缩小,旋转,每个实例中的图像都会以最佳质量渲染。

概念示例

var ctx = c.getContext("2d"), img = new Image;   // these lines just for demo init.
img.onload = demo;
ctx.fillText("Loading image...", 20, 20);
ctx.globalCompositeOperation = "copy";
img.src = "http://i.imgur.com/sPrSId0.jpg";

function demo() {
  render(); 
  zin.onclick = zoomIn;                          // accumulates transform, but render
  zout.onclick = zoomOut;                        //  based on original image using.
  zrot.onclick = rotate;                         //  current transformation matrix
}

function render() {ctx.drawImage(img, 0, 0)}     // render original image

function zoomIn() {
  ctx.translate(c.width * 0.5, c.height * 0.5);  // pivot = center
  ctx.scale(1.05, 1.05);
  ctx.translate(-c.width * 0.5, -c.height * 0.5);
  render();
}

function zoomOut() {
  ctx.translate(c.width * 0.5, c.height * 0.5);
  ctx.scale(1/1.05, 1/1.05);
  ctx.translate(-c.width * 0.5, -c.height * 0.5);
  render();
}

function rotate() {
  ctx.translate(c.width * 0.5, c.height * 0.5);
  ctx.rotate(0.3);
  ctx.translate(-c.width * 0.5, -c.height * 0.5);
  render();
}
<button id=zin>Zoom in</button>
<button id=zout>Zoom out</button>
<button id=zrot>Rotate</button><br>
<canvas id=c width=640 height=378></canvas>