如何在画布上重绘在不模糊的情况下调整大小

How redraw on canvas resize without blurring?

本文关键字:模糊 情况下 调整      更新时间:2023-09-26

当画布元素调整大小(通过样式更改(时,我也想缩放画布绘制的图像。我不能只更改高度/宽度,因为这会导致画布自行清除,所以我这样做:

  1. 创建临时画布元素
  2. 将当前画布的图像绘制到该临时画布上
  3. 调整当前画布的大小
  4. 将临时画布的图像绘制回当前画布,但缩放到新大小

这会导致一些模糊 - 在多次调整大小后非常明显(例如:拖动以调整大小时(。我将如何在没有任何模糊的情况下做到这一点?

编辑:关闭图像平滑(context.webkitImageSmoothingEnabled = false;(并不能解决问题,它只是使它重新绘制它越来越锯齿状,直到图像在多次调整大小后看起来与原始图像完全不同。

在调整大小事件时调用:

    var tmpCanvas = null;       
    //Make a temporary canvas
    tmpCanvas = document.createElement( "canvas" );
    //Set its size to be equal
    tmpCanvas.height = originalCanvas.height;
    tmpCanvas.width = originalCanvas.width;
    //Draw our current canvas onto it
    tmpCanvas.getContext( "2d" ).drawImage( originalCanvas, 0, 0 );
    //Set new dimensions
    originalCanvas.width = originalCanvas.offsetWidth;
    originalCanvas.height = originalCanvas.offsetHeight;
    var originalContext = originalCanvas.getContext( "2d" );
    //Set background and colors
    originalContext.fillStyle = "#ffffff";
    originalContext.strokeStyle = "#000000";
    //Set paintbrush
    originalContext.lineWidth = 4;
    originalContext.lineCap = "round";
    //Fill background as white
    originalContext.fillRect( 0, 0, originalCanvas.width, originalCanvas.height );
    //We have a saved signature
    if ( SignatureCanvas.hasSignature === true )
    {
        //Draw it back but scaled (results in blurred image)
        originalContext.drawImage( tmpCanvas, 0, 0, tmpCanvas.width, tmpCanvas.height, 0, 0, originalCanvas.width, originalCanvas.height );
        /** 
         * This results in a blurred image as well
         //Draw it back but scaled
         originalContext.scale( originalCanvas.width / tmpCanvas.width, originalCanvas.height / tmpCanvas.height );
         originalContext.drawImage( tmpCanvas, 0, 0, tmpCanvas.width, tmpCanvas.height, 0, 0, tmpCanvas.width, tmpCanvas.height );
         */
    }

有没有办法获得笔触并"缩放"所有这些点并重新绘制?

与其从原始画布中获取渲染的图像,不如实际重绘图像。我的意思是执行与原始画布相同的逻辑,但所涉及的点缩放到新大小。

如果可以,请考虑改用 SVG。它本质上可以很好地扩展。

编辑:我想到的另一种选择是简单地使用一个巨大的画布开始。缩小尺寸往往比调整尺寸更好,尤其是在启用平滑的情况下。

编辑二:最初的答案无关紧要,尽管我所做的评论是相关的,现在正在推广它并将其编辑为答案......反正我给出的答案也不是那么好**。

当然,如果您放大光栅图形,即从像素尺寸较小的图像中,创建像素尺寸较高的图像,您将获得模糊的图像。通过放大,您可以使低分辨率图片具有高分辨率,但没有高分辨率细节

除非您

对光栅图像进行多个额外的假设,例如您看到的唯一灰色是在图像边缘,否则绝对无法解决这种模糊问题,或者拐角只能出现在明显的拐点处,其中连接曲线的切线之间的角度必须为 100 度或更小。 从本质上讲,您必须提供其他信息,以便您的高分辨率图像可以"填充"细节。 这与从栅格对 SVG 进行逆向工程并没有太大区别。

因此,您似乎想要模拟缩放矢量图形,其中唯一的解决方案是保存命令,绘制SVG或绘制到更大的画布,如Stuart Branham建议的那样。

** 我最初建议调用drawImage即使没有缩放也会扭曲像素,并且最好使用实际像素数据。 如果这是真的,我找不到证据,但这无关紧要,因为他希望他的图像放大,而不模糊......正如我刚才提到的,这是不可能的。