QQuickPaintedItem中使用世界变换矩阵时QImage显示倒置的解决方法
解决QQuickPaintedItem中drawImage因笛卡尔坐标系变换导致的Y轴倒置问题
你的问题核心是:为了实现笛卡尔坐标系的Y轴向上,给QPainter设置了带负Y分量的世界变换,但drawImage默认以图片左上角为原点绘制,跟着变换被翻转,导致图片倒置。下面提供三种直接可行的解决方法:
方法一:翻转drawImage的源矩形Y轴
直接修改drawImage的源矩形参数,让QPainter从图片的左下角开始取像素,抵消全局变换的Y轴翻转:
void DrawArea::paint(QPainter *painter) { painter->setRenderHint(QPainter::Antialiasing, true); QTransform transform; transform.setMatrix(800.0/10.0, 0.0, 0.0, 0.0, -600.0/10.0, 0.0, 400, 300, 1.0); painter->setWorldTransform(transform); // 修改源矩形的Y起始点为图片高度,高度设为负值 painter->drawImage(QRectF(0, 0, 3, 3), m_image, QRectF(0, m_image.height(), m_image.width(), -m_image.height())); }
原理:源矩形的QRectF(0, m_image.height(), m_image.width(), -m_image.height())会让QPainter从图片底部向上读取像素,刚好抵消全局变换的Y轴翻转,图片将正常显示在笛卡尔坐标系的(0,0)到(3,3)区域。
方法二:给图片单独应用反向变换
在绘制图片前临时保存当前变换,追加一次Y轴翻转,绘制完成后恢复原变换:
void DrawArea::paint(QPainter *painter) { painter->setRenderHint(QPainter::Antialiasing, true); QTransform transform; transform.setMatrix(800.0/10.0, 0.0, 0.0, 0.0, -600.0/10.0, 0.0, 400, 300, 1.0); painter->setWorldTransform(transform); painter->save(); // 保存当前全局变换 painter->scale(1, -1); // 针对图片做Y轴翻转,抵消全局变换的影响 painter->drawImage(QRectF(0, 0, 3, 3), m_image); painter->restore(); // 恢复全局变换,不影响后续绘制 }
原理:两次Y轴翻转(全局变换一次,图片绘制时一次)相互抵消,图片保持正常方向,同时全局的笛卡尔坐标系变换不受影响。
方法三:调整矩阵并修正绘制位置
如果不想修改drawImage的参数,可以将矩阵的Y分量改为正,然后调整图片的绘制Y坐标,让它落在笛卡尔坐标系的正确区域:
void DrawArea::paint(QPainter *painter) { painter->setRenderHint(QPainter::Antialiasing, true); QTransform transform; // 将Y分量改为正,恢复屏幕默认Y轴向下的方向 transform.setMatrix(800.0/10.0, 0.0, 0.0, 0.0, 600.0/10.0, 0.0, 400, 300, 1.0); painter->setWorldTransform(transform); // 绘制Y起点设为-3,让图片顶部对齐笛卡尔Y=3,底部对齐Y=0 painter->drawImage(QRectF(0, -3, 3, 3), m_image); }
原理:矩阵Y分量为正后,屏幕Y向下对应笛卡尔Y向下,所以将绘制位置的Y设为-3,图片会从笛卡尔Y=0向上延伸到Y=3,符合预期的坐标系范围。
内容的提问来源于stack exchange,提问作者James Hao
相关产品推荐
相关产品推荐

