Как масштабировать imageData в HTML canvas?

У меня есть холст на моей веб-странице; Я создаю новые данные изображения на этом холсте, затем я изменяю некоторый пиксель через myImgData.массив данных. Теперь я хотел бы масштабировать это изображение и сделать его больше. Я попытался масштабировать контекст, но изображение остается небольшим. Возможно ли это сделать? Спасибо

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

Я надеюсь, что по крайней мере один другой программист сможет скопировать и вставить это в свой редактор, бормоча: "там, если бы не благодать Божья".


вы можете масштабировать холст с помощью метода 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


Я знаю, что это старая тема, но так как такие люди, как могут найти ее полезной, я добавляю свою оптимизацию в код 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 секунд.


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