div - Cómo escalar un imageData en el lienzo HTML?
title html css (5)
La respuesta de @ Castrohenge funciona, pero, como lo señala Muhammad Umer, desordena las coordenadas del mouse en el lienzo original después de eso. Si desea mantener la capacidad de realizar escalas adicionales (para recortar, etc.), entonces necesita utilizar un segundo lienzo (para escalar) y luego buscar los datos de imagen del segundo lienzo y ponerlos en el lienzo original. Al igual que:
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;
}
Tengo un lienzo en mi página web; Creo un nuevo dato de Imagen en este lienzo y luego modifico un poco de píxel a través de myImgData.data [] array. Ahora me gustaría escalar esta imagen y agrandarla. Intenté escalando el contexto pero la imagen sigue siendo pequeña. ¿Es posible hacer esto? Gracias
Necesitaba hacerlo sin la interpolación que provoca putImageData (), así que lo hice escalando los datos de la imagen en un nuevo objeto ImageData con el tamaño cambiado. No puedo pensar en otra ocasión en la que haya pensado que usar 5 bucles anidados era una buena idea:
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;
}
Espero que al menos otro programador pueda copiar y pegar esto en su editor mientras murmura: "Ahí, por la gracia de Dios, yo".
Puede dibujar imageData en un nuevo lienzo, escalar el lienzo original y luego dibujar el nuevo lienzo en el lienzo original.
Algo como esto debería funcionar:
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);
Aquí hay una demostración funcional http://jsfiddle.net/Hm2xq/2/ .
Puede escalar el lienzo usando el método drawImage.
context = canvas.getContext(''2d'');
context.drawImage( canvas, 0, 0, 2*canvas.width, 2*canvas.height );
Esto escalaría la imagen para duplicar el tamaño y representar la parte noroeste del lienzo. El escalado se logra con los parámetros tercero y cuarto del método drawImage, que especifican el ancho y el alto resultantes de la imagen.
Consulte los documentos en MDN https://developer.mozilla.org/en-US/docs/DOM/CanvasRenderingContext2D#drawImage%28%29
Sé que es un tema antiguo, pero como a las personas les puede resultar útil, agrego mi optimización al código de 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;
}
Este código usa menos bucles y se ejecuta aproximadamente 30 veces más rápido. Por ejemplo, en un zoom de 100x de un área de 100 * 100, este código toma 250 ms mientras que el otro tarda más de 8 segundos.