【问题标题】:Pixel perfect scaling of images while zooming the canvas with fabric.js使用 fabric.js 缩放画布时图像的像素完美缩放
【发布时间】:2015-06-20 09:48:48
【问题描述】:

我的软件是一种带有画笔的像素艺术绘画程序,fabric.js 进行了大量修改,以便对 fabric.js 对象进行像素舍入转换(位置始终是整数),但是调整图像大小并制作它们像素以 1:1 的比例适合画布仍然是个问题。

现在,fabric.js zoomToPoint 函数用于能够使用鼠标滚轮在画布上缩放,当图像未缩放时,它们的像素适合画布但是当我缩小任何对象时(或向上),像素不再适合画布,因此对象的像素实际上小于或大于画布像素。

缩放级别为 8 的问题截图:

原始图像尺寸(没问题,每个像素都适合画布像素)

调整大小的图像,图像的像素不再适合画布像素

图像的像素在缩放时如何以 1:1 的比例适合画布像素?

【问题讨论】:

    标签: javascript html fabricjs


    【解决方案1】:

    就其本质而言,调整大小涉及对原始图像重新采样并将现有像素插值/卷积到调整大小的空间中。生成的图像旨在以其新尺寸在视觉上吸引人。但是对于由X 调整大小的图像,生成的像素肯定不再具有 X:1 关系。

    要放大,您需要一个“投影”,其中每个 1x1 像素都扩展为 2x2 像素组(或 3x3 像素组等)。

    要缩小,您需要一个“投影”,其中每个 2x2 像素组被压缩成一个 1x1 像素集。

    要缩小,源(缩放前)必须由像素组组成。这意味着您不能在不使用重采样的情况下将图像缩小到低于其原始尺寸。没有投影可用于缩小到 1X 以下。一种解决方法是让用户以 2X(或 3X 或 4X)投影进行绘制,以便您可以缩小。

    FabricJS 本身不进行投影...您必须使用临时画布元素来进行投影。

    以下是使用投影进行缩放的示例代码:

    var zoom=2;
    var img=new Image();
    img.crossOrigin='anonymous';
    img.onload=start;
    //img.src="sun.png";
    img.src="https://dl.dropboxusercontent.com/u/139992952/multple/sun.png";
    function start(){
    
      var iw=img.width;
      var ih=img.height;   
    
      img.width=iw;
      img.height=ih;
      // set the "current zoom factor" on the original image to 1x
      img.zoom=1;
    
      // test: resize by 4X
      var zoom4x=resize(img,4,'canvas4x');
      document.body.appendChild(zoom4x);
    
      // test: resize the 4X back down to 2X
      var zoom2x=resize(zoom4x,0.50,'canvas2x');
      document.body.appendChild(zoom2x);
    
      // test: resize the 2X back down to 1X
      var zoom1x=resize(zoom2x,0.50,'canvas1x');
      document.body.appendChild(zoom1x);
    
      // test: resize the 1X down to half-size
      var zoomHx=resize(zoom1x,0.50,'canvas1x');
      if(zoomHx){document.body.appendChild(zoomHx)};
    
      // display the original image
      document.body.appendChild(img);
    
    
    }
    
    
    
    var resize = function(img,scale,id){
    
      var zoom=parseInt(img.zoom*scale);
      if(zoom<1){
        console.log('Cannot recale image to less than original size');
        return;
      }
    
      // get the pixels from the original img using a canvas
      var c1=document.createElement('canvas');
      var cw1=c1.width=img.width;
      var ch1=c1.height=img.height;
      var ctx1=c1.getContext('2d');
      ctx1.drawImage(img,0,0);
      var imgData1=ctx1.getImageData(0,0,cw1,ch1);
      var data1=imgData1.data;
    
      // create a canvas to hold the resized pixels
      var c2=document.createElement('canvas');
      c2.id=id;
      c2.zoom=zoom;
      var cw2=c2.width=cw1*scale;
      var ch2=c2.height=ch1*scale;
      var ctx2=c2.getContext('2d');
      var imgData2=ctx2.getImageData(0,0,cw2,ch2);
      var data2=imgData2.data;
    
      // copy each source pixel from c1's data1 into the c2's data2
      for(var y=0; y<ch2; y++) {
        for(var x=0; x<cw2; x++) {
          var i1=(Math.floor(y/scale)*cw1+Math.floor(x/scale))*4;
          var i2 =(y*cw2+x)*4;            
          data2[i2]   = data1[i1];
          data2[i2+1] = data1[i1+1];
          data2[i2+2] = data1[i1+2];
          data2[i2+3] = data1[i1+3];
        }
      }
    
      // put the modified pixels back onto c2
      ctx2.putImageData(imgData2,0,0);
    
      // return the canvas with the zoomed pixels
      return(c2);
    }
    body{ background-color: ivory; }
    canvas{border:1px solid red;}
    &lt;h4&gt;Left: 4X, 2X, 1X projections, Right:Original Image&lt;/h4&gt;

    【讨论】:

      猜你喜欢
      • 2014-05-17
      • 2012-09-25
      • 1970-01-01
      • 2020-11-04
      • 2015-09-15
      • 2015-04-02
      • 2012-06-06
      • 1970-01-01
      • 2021-05-03
      相关资源
      最近更新 更多