C++ 使用Qt/QML从图像中获取特定像素及其坐标

C++ 使用Qt/QML从图像中获取特定像素及其坐标,c++,image,qt,qml,collision,C++,Image,Qt,Qml,Collision,我们正在创建一个有地图的游戏。在这些地图上,玩家可以行走,但要知道他们是否可以行走,我们有另一张图片,路径是绘制的 玩家可以通过点击地图来移动,如果点击与碰撞器图像匹配,角色应该使用探路器到达点击点。如果不是,则角色不移动 例如,以下是贴图及其碰撞路径图像: 我怎么知道我是否在Qt中单击了collider(这是一个只有一种颜色和透明度的png)? 我使用QML和FelGo进行渲染,所以如果已经有一种方法可以用QML来做,它甚至更好,但是我也可以在C++中实现。 我的第二个问题是如何做探路者?

我们正在创建一个有地图的游戏。在这些地图上,玩家可以行走,但要知道他们是否可以行走,我们有另一张图片,路径是绘制的

玩家可以通过点击地图来移动,如果点击与碰撞器图像匹配,角色应该使用探路器到达点击点。如果不是,则角色不移动

例如,以下是贴图及其碰撞路径图像:

我怎么知道我是否在Qt中单击了collider(这是一个只有一种颜色和透明度的png)? 我使用QML和FelGo进行渲染,所以如果已经有一种方法可以用QML来做,它甚至更好,但是我也可以在C++中实现。 我的第二个问题是如何做探路者?我知道算法,但我应该用像素移动吗

我已经看到了
QPainterPath
类,这可能是我正在寻找的,我如何读取图像中具有特定颜色的所有像素并知道它们的坐标

谢谢

  • QML接口不能提供有效的方法来解决您的任务。应该在C++侧进行。
  • 要获取图像数据,您可以使用:
    • QImage加载图像
    • 调用N次,每次读取K个像素。N等于以像素为单位的图像高度,K等于宽度
如何处理
QImage::constScanLine
返回的
uchar*

您应该调用
QImage::format()
来确定
uchar*
隐藏的像素格式。或者您可以调用
QImage::convertToFormat(QImage::Format\u RGB32)
并始终将像素数据从
uchar*
强制转换到自定义结构,如
PixelData

#pragma pack(push, 1)
struct PixelData {
   uint8_t padding;
   uint8_t r;
   uint8_t g;
   uint8_t b;
};
#pragma pack(pop)
根据本文件:

以下是可编译的解决方案,用于将图像加载到RAM中,以便进一步有效地处理其数据:

#include <QImage>


#pragma pack(push, 1)
struct PixelData {
   uint8_t padding;
   uint8_t r;
   uint8_t g;
   uint8_t b;
};
#pragma pack(pop)


void loadImage(const char* path, int& w, int& h, PixelData** data) {
    Q_ASSERT(data);

    QImage initialImage;
    initialImage.load(path);
    auto image = initialImage.convertToFormat(QImage::Format_RGB32);

    w = image.width();
    h = image.height();
    *data = new PixelData[w * h];

    PixelData* outData = *data;

    for (int y = 0; y < h; y++) {
        auto scanLine = image.constScanLine(y);
        memcpy(outData, scanLine, sizeof(PixelData) * w);
        outData += w;
    }
}


void pathfinder(const PixelData* data, int w, int h) {
    // Your algorithm here
}


void cleanupData(PixelData* data) {
    delete[] data;
}


int main(int argc, char *argv[])
{
    int width, height;
    PixelData* data;

    loadImage("D:\\image.png", width, height, &data);
    pathfinder(data, width, height);
    cleanupData(data);

    return 0;
}
。。。或者在您的寻路算法中的某个地方使用此公式,这样会更有效。

  • QML接口不能提供有效的方法来解决您的任务。应该在C++侧进行。
  • 要获取图像数据,您可以使用:
    • QImage加载图像
    • 调用N次,每次读取K个像素。N等于以像素为单位的图像高度,K等于宽度
如何处理
QImage::constScanLine
返回的
uchar*

您应该调用
QImage::format()
来确定
uchar*
隐藏的像素格式。或者您可以调用
QImage::convertToFormat(QImage::Format\u RGB32)
并始终将像素数据从
uchar*
强制转换到自定义结构,如
PixelData

#pragma pack(push, 1)
struct PixelData {
   uint8_t padding;
   uint8_t r;
   uint8_t g;
   uint8_t b;
};
#pragma pack(pop)
根据本文件:

以下是可编译的解决方案,用于将图像加载到RAM中,以便进一步有效地处理其数据:

#include <QImage>


#pragma pack(push, 1)
struct PixelData {
   uint8_t padding;
   uint8_t r;
   uint8_t g;
   uint8_t b;
};
#pragma pack(pop)


void loadImage(const char* path, int& w, int& h, PixelData** data) {
    Q_ASSERT(data);

    QImage initialImage;
    initialImage.load(path);
    auto image = initialImage.convertToFormat(QImage::Format_RGB32);

    w = image.width();
    h = image.height();
    *data = new PixelData[w * h];

    PixelData* outData = *data;

    for (int y = 0; y < h; y++) {
        auto scanLine = image.constScanLine(y);
        memcpy(outData, scanLine, sizeof(PixelData) * w);
        outData += w;
    }
}


void pathfinder(const PixelData* data, int w, int h) {
    // Your algorithm here
}


void cleanupData(PixelData* data) {
    delete[] data;
}


int main(int argc, char *argv[])
{
    int width, height;
    PixelData* data;

    loadImage("D:\\image.png", width, height, &data);
    pathfinder(data, width, height);
    cleanupData(data);

    return 0;
}

。。。或者在寻路算法中的某个地方使用此公式,这样会更有效。

您可以使用从当前位置到目标位置的一条线,并检查遮罩中该线上的所有像素(第二幅图像)。计算直线上的像素(坐标),我想到了。(而且,我一直认为这些知识现在已经过时了……;-)对不起,我忘了告诉你玩家应该如何移动(我已经编辑了我的帖子)。你的算法的问题是,我的播放器只能在一条线上移动,它不允许以路径移动。最后,我的问题是如何读取图像的像素并将其转换为Qt的coordonate。我不想要路径算法,我知道其中的一些算法(但我很乐意接受这些技巧),那么呢?@folibis在阅读文档后,似乎不建议使用QImage::pixel()进行大规模操作。但是我想为我的探路者创建一个像素地图。所以我需要检查所有像素!如果我只是在一开始就这么做,这是否被视为“大规模操纵”?文档建议使用QImage::constBits(),但它返回第一个像素的uchar,我不知道如何使用它检查所有像素的颜色值……您可以使用从当前位置到目标位置的一条线,并检查遮罩中该线上的所有像素(第二张图像)。计算直线上的像素(坐标),我想到了。(而且,我一直认为这些知识现在已经过时了……;-)对不起,我忘了告诉你玩家应该如何移动(我已经编辑了我的帖子)。你的算法的问题是,我的播放器只能在一条线上移动,它不允许以路径移动。最后,我的问题是如何读取图像的像素并将其转换为Qt的coordonate。我不想要路径算法,我知道其中的一些算法(但我很乐意接受这些技巧),那么呢?@folibis在阅读文档后,似乎不建议使用QImage::pixel()进行大规模操作。但是我想为我的探路者创建一个像素地图。所以我需要检查所有像素!如果我只是在一开始就这么做,这是否被视为“大规模操纵”?文档建议使用QImage::constBits(),但它返回第一个像素的uchar,我不知道如何使用它检查所有像素的颜色值。。。