Canvas平移旋转后使用getImageData提取指定图像区域的问题
问题
我尝试用Canvas的getImageData提取图像中旋转后的矩形区域,但translate和rotate这类变换对getImageData完全无效,没法正确拿到目标区域的数据。目标区域是图中黑色边框的旋转矩形:

当前代码如下:
JavaScript
var c = document.getElementById("myCanvas"); var ctx = c.getContext("2d"); var img = new Image(); img.onload = function() { ctx.drawImage(img, 0, 0, img.width, img.height); drawRect(); } img.src = "https://dummyimage.com/300x150/5873f0/ffffff.jpg"; function drawRect() { ctx.save(); ctx.translate(75, 100); ctx.rotate(20 * Math.PI / 180) // 这行无法获取正确的旋转区域数据 // imgData = ctx.getImageData(-50, -25, 100, 50); ctx.strokeStyle = 'black'; ctx.strokeRect(-50, -25, 100, 50); ctx.restore() }
HTML
<canvas id="myCanvas" width="300" height="150"> Your browser does not support the HTML5 canvas tag. </canvas>
解决方法
getImageData是基于画布原始坐标系统的,完全不受translate、rotate等变换影响,所以直接调用拿不到旋转区域。可以用临时画布绕开这个限制,具体步骤如下:
核心思路
- 创建一个和目标矩形尺寸相同的临时画布;
- 在临时画布上反向旋转,把原图像的旋转区域“转正”后绘制进去;
- 直接从临时画布提取图像数据。
修改后的完整代码
var c = document.getElementById("myCanvas"); var ctx = c.getContext("2d"); var img = new Image(); img.crossOrigin = "anonymous"; // 处理跨域图片操作限制 img.onload = function() { ctx.drawImage(img, 0, 0, img.width, img.height); drawRect(); // 提取旋转区域的图像数据 const rotatedData = getRotatedRegion(img, 75, 100, 20, 100, 50); // 将提取的数据绘制到画布右上角,验证结果 ctx.putImageData(rotatedData, c.width - rotatedData.width - 10, 10); } img.src = "https://dummyimage.com/300x150/5873f0/ffffff.jpg"; function drawRect() { ctx.save(); ctx.translate(75, 100); ctx.rotate(20 * Math.PI / 180) ctx.strokeStyle = 'black'; ctx.strokeRect(-50, -25, 100, 50); ctx.restore() } // 提取指定旋转区域的图像数据 function getRotatedRegion(image, centerX, centerY, angleDeg, rectWidth, rectHeight) { const tempCanvas = document.createElement('canvas'); tempCanvas.width = rectWidth; tempCanvas.height = rectHeight; const tempCtx = tempCanvas.getContext('2d'); const angleRad = angleDeg * Math.PI / 180; // 临时画布变换:先移到中心,反向旋转,再定位到原图像的旋转中心 tempCtx.save(); tempCtx.translate(rectWidth/2, rectHeight/2); tempCtx.rotate(-angleRad); // 反向旋转,让原图像的旋转区域转正 tempCtx.translate(-centerX, -centerY); // 绘制原图像,覆盖临时画布 tempCtx.drawImage(image, 0, 0); tempCtx.restore(); // 提取临时画布的图像数据 return tempCtx.getImageData(0, 0, rectWidth, rectHeight); }
说明
getRotatedRegion函数是核心:通过临时画布的反向旋转,把原图像中旋转的区域转正后绘制,这样getImageData就能拿到正确的矩形数据;- 添加
img.crossOrigin = "anonymous"是为了解决跨域图片无法进行像素操作的问题; - 最后把提取的数据绘制到原画布右上角,方便直观验证结果是否正确。
内容的提问来源于stack exchange,提问作者Matthieu Planté
相关产品推荐
相关产品推荐

