Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/82.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在不缩放的情况下使用HTML5画布翻转图像_Html_Canvas_Drawimage - Fatal编程技术网

如何在不缩放的情况下使用HTML5画布翻转图像

如何在不缩放的情况下使用HTML5画布翻转图像,html,canvas,drawimage,Html,Canvas,Drawimage,我使用HTML5Canvas元素在web应用程序中显示图像,我希望在不向画布应用缩放变换的情况下水平翻转图像。这意味着我不想用于此目的,因为我不想翻转任何其他内容 // 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 properl

我使用HTML5Canvas元素在web应用程序中显示图像,我希望在不向画布应用缩放变换的情况下水平翻转图像。这意味着我不想用于此目的,因为我不想翻转任何其他内容

// 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();
在我看来,我应该能够使用该方法实现这一点,因为该页面显示:

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);
此处的工作示例:

但是如果我尝试按照描述翻转图像,我会在Firefox中遇到以下错误:

ctx.drawImage(image, 0, 0, -image.width, image.height, 0, 0, image.width, image.height);
IndexSizeError:索引或大小为负或大于允许的值 数量


我不明白我做错了什么。如何在不缩放画布的情况下水平翻转图像?

一个相当简单的解决方案是使用第二个画布,在那里只绘制翻转一次的图像,然后将另一个画布的该部分绘制到主画布上。这将成功创建图像的翻转版本,并缓存,您可以在任何地方绘制它。

负片区域似乎不受支持(尚未?),或

必须在原始方向上处理图像数据,即使 给出的尺寸是负数

在任何情况下,我们都不能对此做太多,只能寻找替代方法-

不过,这给您留下了一些选择—我假设您希望避免使用保存/恢复,并且您可以这样做-

重置转换

这是最快的方法,但您需要知道它将重置任何转换。在大多数情况下,这可能是正常的,因此:

ctx.scale(-1, 1);
ctx.drawImage(image, -image.width, 0);
ctx.setTransform(1, 0, 0, 1, 0, 0);
最后一个调用是使用单位矩阵重置转换矩阵

反转上次转换操作

如果依赖于其他转换,则可以简单地反转上一个转换操作。这是第二快的选项(它需要在内部执行矩阵乘法):

使用保存/恢复

正如你已经知道的。。。但是速度很慢,因为它保存和恢复画布的整个状态,而不仅仅是转换

手动翻转

如果出于某种原因要求根本不使用转换,则始终可以逐个扫描线翻转它。这是第二个效率最低的方法,但它允许您在不进行转换的情况下工作,并允许您执行其他操作,如替换:

for(var x = 0; x < width; x++)
    ctx.drawImage(img, x, 0, 1, height, width - x, 0, 1, height);
for(变量x=0;x
(宽度和高度是图像的宽度和高度)

像素操作


最后一个,只是为了记录,当然是获取像素数据并循环,切换位置等。这是最慢的方法,取决于CORS要求,不建议使用此方法。

Upvote以获得好的答案。需要明确的是,您的第二个画布可以是主画布的图像源,无需转换为图像
mainContext.drawImage(flippingCanvas,125,50)
。感谢您的快速回答!你的方法很有效,但在我的特定应用程序中,它带来了其他复杂问题(不是你的错;仍然让你放弃投票)。Ken的第一个方法最容易实现,并且在我的应用程序中没有副作用?我想看看这两个画布是如何实施的。至少,你会这么做的。谢谢你详尽的回答,肯!我同意你的第一种方法。事实证明,缩放毕竟可以正常工作,只要在之后重置转换(我第一次使用
scale()
restore()
进行测试时犯了一个错误)。你对消极区域的看法似乎是正确的;在现行的HTML标准中没有提到它。该Mozilla页面需要更新。我第一次使用
scale()
restore()
进行测试时犯了一个错误。这实际上很好。我更新了Mozilla页面的
drawImage()
,因为规范中没有提到带负值的图像翻转。
for(var x = 0; x < width; x++)
    ctx.drawImage(img, x, 0, 1, height, width - x, 0, 1, height);