Как перевернуть изображение с помощью HTML5 canvas без масштабирования
Я использую элемент HTML5 canvas для отображения изображения в веб-приложении, и я хочу перевернуть изображение по горизонталибез применения преобразования масштабирования к холсту. Это означает, что я не хочу использовать CanvasRenderingContext2D.scale() для этой цели, потому что я не хочу переворачивать что-либо еще.
// I don't want this, because it breaks the rest of the application. I have
// implemented zooming and landmark placement functionality, which no longer
// work properly after scaling.
ctx.save();
ctx.scale(-1, 1);
ctx.drawImage(image, -image.width, 0, image.width, image.height);
ctx.restore();
Мне кажется, что я должен быть в состоянии сделать это с помощью метода CanvasRenderingContext2D.drawImage(), так как эта страница читает:
SWidth: ширина под-прямоугольника исходного изображения, который нужно нарисовать в контексте назначения. Если не задано, то используется весь прямоугольник от координат, заданных SX и sy, до нижнего правого угла изображения. если задано отрицательное значение, то при рисовании изображение переворачивается по горизонтали.
Вот как я рисую изображение:
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var image = document.getElementById('source');
ctx.drawImage(image, 0, 0, image.width, image.height, 0, 0, image.width, image.height);
Рабочий пример здесь: https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/drawImage#Using_the_drawImage_method
Но если я попытаюсь перевернуть изображение в соответствии с описанием, я получу следующую ошибку в Firefox:
ctx.drawImage(image, 0, 0, -image.width, image.height, 0, 0, image.width, image.height);
Я не понимаю, что я здесь делаю не так. Как перевернуть изображение по горизонтали без масштабирования холста?IndexSizeError: индекс или размер отрицательный или больше допустимого сумма
2 ответа:
Отрицательная область, по-видимому, не поддерживается (пока?), или эта строка может повлиять на то, как выполняется реализация, см. Шаг 4:
В любом случае, мы ничего не можем с этим поделать, кроме как посмотреть на альтернативные пути -Данные изображения должны обрабатываться в исходном направлении, даже если приведенные измерения отрицательны.
Это оставляет вам некоторые варианты, хотя-я предполагаю, что вы хотите избежать использования save / restore, и вы можете -
Преобразование сброса
Это самый быстрый метод, но вы должны знать, что он сбросит любое преобразование. И это может быть нормально в большинстве случаев, так что:Последний вызов-сброс матрицы преобразования с использованием матрицы идентификации.ctx.scale(-1, 1); ctx.drawImage(image, -image.width, 0); ctx.setTransform(1, 0, 0, 1, 0, 0);
Реверсирование последней операции преобразования
Если вы зависите от других преобразований, вы можете просто отменить последнюю операцию преобразования. Это второй самый быстрый вариант (он нужен чтобы сделать умножение матрицы внутренне):
ctx.scale(-1, 1); ctx.drawImage(image, -image.width, 0); ctx.scale(-1, 1); // revert scale only
Использование save / restore
Как вы уже знаете... но медленно, так как это сохраняет и восстанавливает все состояние холста, а не только трансформацию.
Листать вручную
Если по какой-то причине требуется вообще не использовать преобразование, вы всегда можете перевернуть его scanline by scanline. Это второй наименее эффективный метод, но он позволяет работать без преобразований, и это действительно позволяет вы должны делать другие вещи, такие как перемещение:
for(var x = 0; x < width; x++) ctx.drawImage(img, x, 0, 1, height, width - x, 0, 1, height);
(ширина и высота-это ширина и высота изображения).
Манипуляция пикселями
И последнее, просто для записи, конечно, чтобы получить пиксельные данные и цикл через, переключение мест и т.д. Это самый медленный метод, и он зависит от требований CORS, и не рекомендуется для этого.
Довольно простым решением было бы использовать второй холст, нарисовать там изображение, перевернутое только один раз, а затем нарисовать эту часть другого холста на главном холсте. Это позволило бы успешно создать перевернутую версию вашего изображения, кэшированную, и вы можете рисовать ее везде, где захотите.