Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在HTML画布中缩放imageData?_Html_Canvas_Getimagedata - Fatal编程技术网

如何在HTML画布中缩放imageData?

如何在HTML画布中缩放imageData?,html,canvas,getimagedata,Html,Canvas,Getimagedata,我有一个画布在我的网页;我在画布中创建了一个新的图像数据,然后通过myImgData.data[]数组修改了一些像素。现在我想缩放这张图片,使它更大。我尝试缩放上下文,但图像仍然很小。有可能这样做吗? 非常感谢您可以将图像数据绘制到新画布,缩放原始画布,然后将新画布绘制到原始画布 像这样的方法应该会奏效: var imageData = context.getImageData(0, 0, 100, 100); var newCanvas = $("<canvas>") .a

我有一个画布在我的网页;我在画布中创建了一个新的图像数据,然后通过myImgData.data[]数组修改了一些像素。现在我想缩放这张图片,使它更大。我尝试缩放上下文,但图像仍然很小。有可能这样做吗?
非常感谢

您可以将图像数据绘制到新画布,缩放原始画布,然后将新画布绘制到原始画布

像这样的方法应该会奏效:

var imageData = context.getImageData(0, 0, 100, 100);
var newCanvas = $("<canvas>")
    .attr("width", imageData.width)
    .attr("height", imageData.height)[0];

newCanvas.getContext("2d").putImageData(imageData, 0, 0);

context.scale(1.5, 1.5);
context.drawImage(newCanvas, 0, 0);
var-imageData=context.getImageData(0,00100);
var newCanvas=$(“”)
.attr(“宽度”,imageData.width)
.attr(“高度”,imageData.height)[0];
newCanvas.getContext(“2d”).putImageData(imageData,0,0);
背景量表(1.5,1.5);
drawImage(newCanvas,0,0);

这是一个功能演示。

我需要在不使用putImageData()引起的插值的情况下进行此操作,因此我通过将图像数据缩放到一个新的、调整大小的ImageData对象来完成此操作。我想不出还有哪次我认为使用5个嵌套for循环是个好主意:

function scaleImageData(imageData, scale) {
  var scaled = c.createImageData(imageData.width * scale, imageData.height * scale);

  for(var row = 0; row < imageData.height; row++) {
    for(var col = 0; col < imageData.width; col++) {
      var sourcePixel = [
        imageData.data[(row * imageData.width + col) * 4 + 0],
        imageData.data[(row * imageData.width + col) * 4 + 1],
        imageData.data[(row * imageData.width + col) * 4 + 2],
        imageData.data[(row * imageData.width + col) * 4 + 3]
      ];
      for(var y = 0; y < scale; y++) {
        var destRow = row * scale + y;
        for(var x = 0; x < scale; x++) {
          var destCol = col * scale + x;
          for(var i = 0; i < 4; i++) {
            scaled.data[(destRow * scaled.width + destCol) * 4 + i] =
              sourcePixel[i];
          }
        }
      }
    }
  }

  return scaled;
}
函数scaleImageData(图像数据,比例){
var scaled=c.createImageData(imageData.width*比例,imageData.height*比例);
对于(变量行=0;行

我希望至少有一个程序员可以复制并粘贴到他们的编辑器中,同时喃喃地说,“如果没有上帝的恩典,我就去吧。”

您可以使用drawImage方法缩放画布

context = canvas.getContext('2d');
context.drawImage( canvas, 0, 0, 2*canvas.width, 2*canvas.height );
这将缩放图像,使其大小加倍,并将其西北部分渲染到画布上。缩放是通过drawImage方法的第三个和第四个参数实现的,这些参数指定了生成的图像的宽度和高度


请参阅MDN上的文档我知道这是一个古老的主题,但由于像我这样的人可能会发现它很有用,我将我的优化添加到rodarmor的代码中:

function scaleImageData(imageData, scale) {
    var scaled = ctx.createImageData(imageData.width * scale, imageData.height * scale);
    var subLine = ctx.createImageData(scale, 1).data
    for (var row = 0; row < imageData.height; row++) {
        for (var col = 0; col < imageData.width; col++) {
            var sourcePixel = imageData.data.subarray(
                (row * imageData.width + col) * 4,
                (row * imageData.width + col) * 4 + 4
            );
            for (var x = 0; x < scale; x++) subLine.set(sourcePixel, x*4)
            for (var y = 0; y < scale; y++) {
                var destRow = row * scale + y;
                var destCol = col * scale;
                scaled.data.set(subLine, (destRow * scaled.width + destCol) * 4)
            }
        }
    }

    return scaled;
}
函数scaleImageData(图像数据,比例){
var scaled=ctx.createImageData(imageData.width*比例,imageData.height*比例);
var subLine=ctx.createImageData(比例1).data
对于(变量行=0;行

这段代码使用更少的循环,运行速度大约快30倍。例如,在100*100区域的100倍缩放上,这一编码需要250毫秒,而另一个编码需要8秒以上。

@Castrohenge的答案是有效的,但正如穆罕默德·乌默所指出的,这会在之后弄乱原始画布上的鼠标坐标。如果要保持执行其他缩放(用于裁剪等)的能力,则需要使用第二个画布(用于缩放),然后从第二个画布获取图像数据并将其放入原始画布。像这样:

function scaleImageData(imageData, scale){
    var newCanvas = $("<canvas>")
      .attr("width", imageData.width)
      .attr("height", imageData.height)[0];

    newCanvas.getContext("2d").putImageData(imageData, 0, 0);

    // Second canvas, for scaling
    var scaleCanvas = $("<canvas>")
      .attr("width", canvas.width)
      .attr("height", canvas.height)[0];

    var scaleCtx = scaleCanvas.getContext("2d");

    scaleCtx.scale(scale, scale);
    scaleCtx.drawImage(newCanvas, 0, 0);

    var scaledImageData =  scaleCtx.getImageData(0, 0, scaleCanvas.width, scaleCanvas.height);

    return scaledImageData;
}
函数scaleImageData(图像数据,比例){
var newCanvas=$(“”)
.attr(“宽度”,imageData.width)
.attr(“高度”,imageData.height)[0];
newCanvas.getContext(“2d”).putImageData(imageData,0,0);
//第二个画布,用于缩放
变量scaleCanvas=$(“”)
.attr(“宽度”,canvas.width)
.attr(“高度”,画布高度)[0];
var scaleCtx=scaleCanvas.getContext(“2d”);
scaleCtx.scale(scale,scale);
drawImage(newCanvas,0,0);
var scaledImageData=scaleCtx.getImageData(0,0,scaleCanvas.width,scaleCanvas.height);
返回缩放图像数据;
}

还可以使用更高质量的插值方法,如双线性或样条曲线。@kvantt完全正确,虽然有时你需要那些大块的像素。
c
变量指的是什么?@TomášZato它是画布上下文现在有一个属性可以设置为false,以便在缩放上下文上实现最近邻插值。我想补充一点,你可以在不创建另一个画布的情况下实现这一点ctx.drawImage(ctx.canvas,0,0);将画布绘制到自身上,您可以在绘制时进行缩放。但该缩放也会弄乱坐标10 x为1.5*10。我在这个例子中也有同样的问题:新画布的某些像素的alpha=0。将新画布绘制到原始画布时。阿尔法变成黑色。如何解决这个问题,
canvas.width
canvas.height
,变量
canvas
定义在哪里?我不明白。。。它将画布的内容绘制到同一画布上?