35

Webページにキャンバスがあります。myImgData.data[]このキャンバスに新しい画像データを作成してから、配列を介していくつかのピクセルを変更します。次に、この画像を拡大縮小して大きくしたいと思います。コンテキストをスケーリングしてみましたが、画像が小さいままです。これを行うことは可能ですか?ありがとう

4

5 に答える 5

40

imageDataを新しいキャンバスに描画し、元のキャンバスを拡大縮小してから、新しいキャンバスを元のキャンバスに描画することができます。

このようなものが機能するはずです:

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

これが機能するデモですhttp://jsfiddle.net/Hm2xq/2/

于 2010-08-10T13:26:31.183 に答える
17

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

少なくとも1人の他のプログラマーが、「神の恵みのために私が行ってください」とつぶやきながら、これをコピーしてエディターに貼り付けることができることを願っています。

于 2012-02-04T05:12:14.153 に答える
17

私はそれが古い主題であることを知っています、しかし好きな人々がそれが役に立つと思うかもしれないので、私は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;
}

このコードはループの使用量が少なく、実行速度が約30倍速くなります。たとえば、100 * 100領域の100倍ズームでは、このコードは250ミリ秒かかりますが、他のコードは8秒以上かかります。

于 2013-12-08T10:17:14.957 に答える
13

drawImageメソッドを使用してキャンバスを拡大縮小できます。

context = canvas.getContext('2d');
context.drawImage( canvas, 0, 0, 2*canvas.width, 2*canvas.height );

これにより、画像が2倍のサイズに拡大縮小され、画像の北西部分がキャンバスにレンダリングされます。スケーリングは、drawImageメソッドの3番目と4番目のパラメーターを使用して実現されます。これらのパラメーターは、結果として得られる画像の幅と高さを指定します。

MDNhttps://developer.mozilla.org/en-US/docs/DOM/CanvasRenderingContext2D#drawImage%28%29のドキュメントを参照してください

于 2012-12-18T16:06:48.163 に答える
1

@Castrohengeの答えは機能しますが、Muhammad Umerが指摘しているように、その後、元のキャンバス上のマウス座標が台無しになります。追加のスケール(トリミングなど)を実行する機能を維持する場合は、2番目のキャンバス(スケーリングなど)を使用してから、2番目のキャンバスから画像データをフェッチして元のキャンバスに配置する必要があります。そのようです:

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;
}
于 2016-11-23T19:41:12.453 に答える