使用fabric.js缩放画布时,像素完美缩放图像 [英] Pixel perfect scaling of images while zooming the canvas with fabric.js

查看:2179
本文介绍了使用fabric.js缩放画布时,像素完美缩放图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

My software is a kind of pixel art paint program with brushes, fabric.js was heavily modified in order to have pixel rounded translation (the position is always an integer) for the fabric.js objects, however resizing images and making their pixels fit the canvas in a 1:1 ratio is still an issue.

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

Right now, the fabric.js zoomToPoint function is used to be able to zoom on the canvas with the mouse wheel, when images aren't scaled, their pixels fit with the canvas but when i scale any objects down (or up), pixels does not fit anymore with the canvas so the pixels of the object are actually smaller or bigger than the canvas pixel.

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

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

Original image dimensions (no problems, each pixels fit the canvas pixels)

调整后的图片,图片的像素不再适合画布像素

Resized image, pixels of the image does not fit the canvas pixels anymore

当缩放它们时,图像的像素如何以1:1的比例拟合画布像素?

How can the pixels of the images fit the canvas pixels in a 1:1 ratio when scaling them?

推荐答案

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

By its nature, resizing involves resampling the original image and interpolating/convoluting the existing pixels into the resized space. The resulting image is meant to be visually appealing at its new size. But for an image resized by X, the resulting pixels certainly do not have an X:1 relationship anymore.

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

To zoom-in you need a "projection" where each single 1x1 pixel is expanded into a 2x2 pixel group (or a 3x3 pixel group, etc).

要缩小,您需要一个投影,其中每个2x2像素组会缩合为一个1x1像素集。

To zoom-out you need a "projection" where each 2x2 pixel group is condensed into a single 1x1 pixel set.

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

To zoom-out, the source (before scaling) must be made up of pixel groups. This means that you cannot zoom-out an image below its original size without using resampling. There is no projection available to zoom-out below 1X. A workaround is to have the user draw at 2X (or 3X or 4X) projection so you can zoom-out.

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

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

Here's example code to zoom using projections:

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

<h4>Left: 4X, 2X, 1X projections, Right:Original Image</h4>

这篇关于使用fabric.js缩放画布时,像素完美缩放图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆