【问题标题】:Canvas zoomIn/zoomOut: how to avoid loss of image quality?画布放大/缩小:如何避免图像质量损失?
【发布时间】:2016-09-28 19:32:23
【问题描述】:

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

我使用了屏幕外处理,因为浏览器通过使用双缓冲来优化图像操作。我仍然遇到这样的问题,即当我放大 400% 左右然后缩小回原始大小时,图像质量会显着下降。

我不依赖原图,因为用户可以进行剪辑、裁剪、旋转、注释等很多操作,我需要在原图上叠加所有操作

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

    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();
       };
    }

【问题讨论】:

    标签: image-processing canvas html5-canvas


    【解决方案1】:

    画布是画后忘掉的。如果不参考原始来源,就无法保持原始质量。

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

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

    展示一个执行所有这些步骤的示例有点过于宽泛,但这里有一个示例展示了如何在原始图像上使用累积矩阵变换来保持最佳质量。您可以看到您可以放大和缩小、旋转,并且图像将在每个实例中以最佳质量呈现。

    概念示例

    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>

    【讨论】:

    • 谢谢。今天学习了 globalCompositeOperation。将继续试验。
    猜你喜欢
    • 1970-01-01
    • 2012-06-22
    • 1970-01-01
    • 2015-03-04
    • 1970-01-01
    • 1970-01-01
    • 2016-03-01
    • 2016-04-13
    • 1970-01-01
    相关资源
    最近更新 更多