我的网页中有一个画布;我在这个画布中创建了一个新的图像数据,然后我通过myImgData.data[]
数组修改了一些像素。现在我想缩放这个图像并让它更大。我尝试通过缩放上下文,但图像仍然很小。是否有可能做到这一点?谢谢
5 回答
您可以将 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/。
我需要在没有 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;
}
我希望至少有其他程序员可以将其复制并粘贴到他们的编辑器中,同时喃喃自语:“除了上帝的恩典,我去吧。”
我知道这是一个古老的主题,但由于喜欢的人可能会觉得它很有用,我将我的优化添加到 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 秒以上。
您可以使用 drawImage 方法缩放画布。
context = canvas.getContext('2d');
context.drawImage( canvas, 0, 0, 2*canvas.width, 2*canvas.height );
这会将图像缩放到两倍大小并将其西北部分渲染到画布上。缩放是通过 drawImage 方法的第三个和第四个参数来实现的,它们指定了图像的最终宽度和高度。
请参阅 MDN 上的文档https://developer.mozilla.org/en-US/docs/DOM/CanvasRenderingContext2D#drawImage%28%29
@Castrohenge 的答案有效,但正如 Muhammad Umer 指出的那样,之后它会弄乱原始画布上的鼠标坐标。如果您想保持执行额外缩放(用于裁剪等)的能力,那么您需要使用第二个画布(用于缩放),然后从第二个画布获取图像数据并将其放入原始画布中。像这样:
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;
}