Как исправить деформированные / искаженные и вырезанные изображения в объекте HTML-холста с помощью JavaScript? - PullRequest
2 голосов
/ 14 апреля 2019

Я пытаюсь вырезать максимально возможную квадратную область изображения с помощью функции рисования изображения объекта canvas в HTML5 с помощью JavaScript. Кроме того, вырезанная область должна быть центром исходного изображения.

(я также рисую водяной знак поверх изображения.)

Это прекрасно работает, не пытаясь вырезать центр изображения, но всякий раз, когда я пытался это сделать, результат искажается.

Это деформированное изображение и это как выглядит оригинал

Пример искаженного изображения также приведен во фрагменте кода ниже!

Чтобы вырезать часть изображения, вы должны объявить две координаты P1 и P2 с для каждых 2 переменных.

Система координат вот так (я думаю):

Для расчета P1 и P2 я использую:

ширина изображения <высота изображения </em>


P1:
----
x1 = 0
y1 = (imageheight / 2) - (imagewidth / 2)
// if I'm replacing y1 with 0, it wont get warped
// but it will cut out the top of the image

and

P2:
----
x2 = imagewidth
y2 = y1 + imagewidth

ширина изображения> высота изображения


P1:
----
x1 = (imagewidth / 2) - (imageheight / 2)
y1 = 0
// if I'm replacing x1 with 0, it wont get warped
// but it will cut out the most left part of the image

and

P2:
----
x2 = x1 + imageheight
y2 = imageheight

Вот мой код:

в основном пишет в этот объект:

<div id="buy_imagelist" class=imagelist></div>

JavaScript:

var numbers = ["images/test_images/bluefireoly-2.jpg"];
var txt = "";
var numCanvas = 0;

for(var src in numbers) {
    numCanvas++;
}

var i = 0;
for(var src in numbers) {
    txt = txt + '<canvas class=imagelistsingle style=padding:7px id=myCanvas' + i + ' width="300" height="300"></canvas>';
    i++;
}

document.getElementById('buy_imagelist').innerHTML = txt;
var imageNumber_canvas = 0;

numbers.forEach(myFunction);

function myFunction(value, index, array) {

    var canvas = document.getElementById('myCanvas' + imageNumber_canvas);
    if(canvas == null) {
        window.alert("Error - Images could not be loaded");
    }
    var context = canvas.getContext('2d');

    function loadImages(imagelist, callback) {
        var images = {};
        var loadedImages = 0;
        var numImages = 0;

        for(var src in imagelist) {
            numImages++;
        }

        for(var src in imagelist) {

            images[src] = new Image();
            images[src].onload = function() {
                if(++loadedImages >= numImages) {
                    callback(images);
                }
            };
            images[src].src = imagelist[src];

        }

    }

    var imagelist = {
        testimage: value,
        wasserzeichen: "images/wasserzeichen/wasserzeichen_1.png"
    };

    loadImages(imagelist, function(images) {

        var testimage = images.testimage;

        var imagewidth = testimage.naturalWidth;
        var imageheight = testimage.naturalHeight;

        var x1 = 0;
        var y1 = 0;
        var x2 = imagewidth;
        var y2 = imageheight;

        if(imagewidth !== imageheight) {

            if(imageheight < imagewidth) {

                x1 = (imagewidth / 2) - (imageheight / 2);
                y1 = 0;

                x2 = x1 + imageheight;
                y2 = imageheight;

            } else {

                x1 = 0;
                y1 = (imageheight / 2) - (imagewidth / 2);

                x2 = imagewidth;
                y2 = y1 + imagewidth;

            }

        }

        context.drawImage(testimage, x1, y1, x2, y2, 0, 0, 300, 300);
        context.drawImage(images.wasserzeichen, 0, 0, 300, 300);
    });

    imageNumber_canvas++;

}

Как и ожидалось, это хорошо работает для квадратных изображений.

Ошибка должна быть где-то здесь (особенно там, где я пометил ее "//!")

var testimage = images.testimage;

var imagewidth = testimage.naturalWidth;
var imageheight = testimage.naturalHeight;

var x1 = 0;
var y1 = 0;
var x2 = imagewidth;
var y2 = imageheight;

if(imagewidth !== imageheight) {

    if(imageheight < imagewidth) {

        x1 = (imagewidth / 2) - (imageheight / 2); //!
        y1 = 0;

        x2 = x1 + imageheight;
        y2 = imageheight;

    } else {

        x1 = 0;
        y1 = (imageheight / 2) - (imagewidth / 2); //!

        x2 = imagewidth;
        y2 = y1 + imagewidth;

    }

}

context.drawImage(testimage, x1, y1, x2, y2, 0, 0, 300, 300);
context.drawImage(images.wasserzeichen, 0, 0, 300, 300);

Для неквадратного изображения, указанного выше (1028x1920) (ширина <высота) <br>

-> y1 = 446
-> поэтому y2 = 446 + 1028 = 1474

, поэтому y1> 0
поэтому у2 <высота <br> -> вырезанный квадрат должен соответствовать оригинальному изображению

Используйте этот код, чтобы попробовать его самостоятельно: (нажмите на «полную страницу», чтобы увидеть изображение)

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Example</title>
</head>

<body>

  <div id="buy_imagelist" class=imagelist></div>

  <script>
    var numbers = ["https://i.pinimg.com/originals/46/1c/01/461c0133da95e315cd4e245f79219ec0.jpg"];
    var txt = "";
    var numCanvas = 0;

    for (var src in numbers) {
      numCanvas++;
    }

    var i = 0;
    for (var src in numbers) {
      txt = txt + '<canvas class=imagelistsingle style=padding:7px id=myCanvas' + i + ' width="300" height="300"></canvas>';
      i++;
    }

    document.getElementById('buy_imagelist').innerHTML = txt;
    var imageNumber_canvas = 0;

    numbers.forEach(myFunction);

    function myFunction(value, index, array) {

      var canvas = document.getElementById('myCanvas' + imageNumber_canvas);
      if (canvas == null) {
        window.alert("Error - Images could not be loaded");
      }
      var context = canvas.getContext('2d');

      function loadImages(imagelist, callback) {
        var images = {};
        var loadedImages = 0;
        var numImages = 0;

        for (var src in imagelist) {
          numImages++;
        }

        for (var src in imagelist) {

          images[src] = new Image();
          images[src].onload = function() {
            if (++loadedImages >= numImages) {
              callback(images);
            }
          };
          images[src].src = imagelist[src];

        }

      }

      var imagelist = {
        testimage: value
      };

      loadImages(imagelist, function(images) {

        var testimage = images.testimage;

        var imagewidth = testimage.naturalWidth;
        var imageheight = testimage.naturalHeight;

        var x1 = 0;
        var y1 = 0;
        var x2 = imagewidth;
        var y2 = imageheight;

        if (imagewidth !== imageheight) {

          if (imageheight < imagewidth) {

            x1 = (imagewidth / 2) - (imageheight / 2);
            y1 = 0;

            x2 = x1 + imageheight;
            y2 = imageheight;

          } else {

            x1 = 0;
            y1 = (imageheight / 2) - (imagewidth / 2);

            x2 = imagewidth;
            y2 = y1 + imagewidth;

          }

        }

        context.drawImage(testimage, x1, y1, x2, y2, 0, 0, 300, 300);

      });

      imageNumber_canvas++;

    }
  </script>

</body>

</html>

1 Ответ

1 голос
/ 14 апреля 2019

4-й и 5-й аргументы метода drawImage: width и height, а не x2 и y2.

Документация по MDN использует это в первом примере

ctx.drawImage(image, 33, 71, 104, 124, 21, 20, 87, 104);

с объяснением

Исходное изображение берется из координат (33, 71), шириной 104 и высотой 124. Оно рисуется на холсте в точке (21, 20), где ему присваивается ширина 87 и высота 104.

Т.Л., др

Вы должны указать ширину / высоту вырезанного изображения, а не координаты нижнего правого угла:

context.drawImage(testimage, x1, y1, x2 - x1, y2 - y1, 0, 0, 300, 300);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...