私のWebページにはキャンバスがあります。このキャンバスで新しい画像データを作成し、次にmyImgData.data []配列を介していくつかのピクセルを変更します。次に、この画像を拡大して大きくします。コンテキストをスケーリングしてみましたが、画像は小さいままです。これは可能ですか?ありがとう
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/ です。
私はそれが古い主題であることを知っていますが、好きな人はそれが役に立つと思うかもしれないので、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秒以上かかります。
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人のプログラマがこれをコピーして自分のエディタに貼り付け、「そこには神の恵みが必要だ」というつぶやきを期待しています。
キャンバスは、drawImageメソッドを使用してスケーリングできます。
context = canvas.getContext('2d');
context.drawImage( canvas, 0, 0, 2*canvas.width, 2*canvas.height );
これにより、画像のサイズが2倍に拡大され、画像の北西部分がキャンバスにレンダリングされます。スケーリングは、イメージの結果の幅と高さを指定するdrawImageメソッドの3番目と4番目のパラメーターで実現されます。
MDNのドキュメントを参照 https://developer.mozilla.org/en-US/docs/DOM/CanvasRenderingContext2D#drawImage%28%29
@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;
}