canvas drawImage img 源 vs canvas 源

canvas drawImage img source vs canvas source

我对同一图像使用 drawImage 函数,但当源是 img 元素时与源是 canvas(与原始图像大小相同)时,我得到了不同的结果。

这是代码

  async function draw(src) {

        const mainCanvas = document.getElementById("cnv");
        const ctx = mainCanvas.getContext("2d");
        let img = document.getElementById("img");

        let w = img.width;
        let h = img.height;
        if (src == "cnv") {
         
          const newCnv =      document.createElement("canvas");
          newCnv.width = w;
          newCnv.height = h;

          const newCtx = newCnv.getContext("2d");
          //just to be sure we dont touch the original image data
          newCtx.imageSmoothingEnabled = false;
          // i tested it with all function overloads and still the same
          newCtx.drawImage(img, 0, 0, w, h, 0, 0, w, h);
          img = newCnv;

        }

        let destW = 850;
        const pxr = window.devicePixelRatio;
        let destH = (destW * h) / w;
        mainCanvas.style.width = destW + "px";
        mainCanvas.style.height = destH + "px";

        destW *= pxr;
        destH *= pxr;

        mainCanvas.width = destW;
        mainCanvas.height = destH;

        ctx.imageSmoothingQuality = "high";

        ctx.drawImage(img, 0, 0, destW, destH);
      }
<img
      id="img"
      style="display: none"
      src="https://work.otzar.org/example.png"
    />
<button onclick="draw('img')">drawImage from img</button>
<button onclick="draw('cnv')">drawImage from canvas</button>
<br />
<canvas id="cnv"> </canvas>

我知道当你使用 drawImage 它会做一些工作,例如当目标尺寸较小时缩小比例。但是这里 newCnv 与原始图像相同,所以我不明白为什么 js 需要做一些事情,而不仅仅是将像素数据放在 canvas.

罪魁祸首是 imageSmothingQuality = "high",我以前遇到过,即使使用 ImageBitmaps。
不同的来源会用他们的算法得到不同的结果,即使是两个 JPEG 也会有非常不同的质量,这取决于图像的压缩。

你做得很好opening that issue

请注意,在我的测试中,imageSmothingQuality = "medium" 得到了最好看的结果,它也没有受到此错误的影响。

async function draw(src) {

  const mainCanvas = document.getElementById("cnv");
  const ctx = mainCanvas.getContext("2d");
  let img = document.getElementById("img");

  let w = img.width;
  let h = img.height;
  if (src == "cnv") {

    const newCnv =      document.createElement("canvas");
    newCnv.width = w;
    newCnv.height = h;

    const newCtx = newCnv.getContext("2d");
    //just to be sure we dont touch the original image data
    newCtx.imageSmoothingEnabled = false;
    // i tested it with all function overloads and still the same
    newCtx.drawImage(img, 0, 0, w, h, 0, 0, w, h);
    img = newCnv;

  }

  let destW = 850;
  const pxr = window.devicePixelRatio;
  let destH = (destW * h) / w;
  mainCanvas.style.width = destW + "px";
  mainCanvas.style.height = destH + "px";

  destW *= pxr;
  destH *= pxr;

  mainCanvas.width = destW;
  mainCanvas.height = destH;

  ctx.imageSmoothingQuality = "medium";

  ctx.drawImage(img, 0, 0, destW, destH);
}
<img
      id="img"
      style="display: none"
      src="https://work.otzar.org/example.png"
    />
<button onclick="draw('img')">drawImage from img</button>
<button onclick="draw('cnv')">drawImage from canvas</button>
<br />
<canvas id="cnv"> </canvas>