首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用scanLine()方法将QImage的所有像素存储在C++中

用scanLine()方法将QImage的所有像素存储在C++中
EN

Stack Overflow用户
提问于 2016-11-14 21:44:34
回答 2查看 2.6K关注 0票数 3

我试图使用QtscanLine()方法修改图像。此方法返回指向给定行的数据的指针。我创建了如何读取行这里。现在,我能够读取如下所有像素的值:

代码语言:javascript
复制
QRgb ** pixels;

pixels = (QRgb **) (malloc(sizeof (QRgb*) * img->width() * img->height()));

#pragma omp parallel for
for (int y = 0; y < img->height(); ++y) {
    pixels[y] = (QRgb*) img->scanLine(y);
}

for (int x = 0; x < img->width(); ++x) {
    for (int y = 0; y < img->height(); ++y) {
        int color =  qRed(pixels[y][x]);
        std::cout << "Pixel at " << x << ", " << y << " is " << color << std::endl;
    }
}

然后,我处理每个像素并尝试在一个新的QRgb **变量中添加这些像素,但这是程序在执行过程中失败的地方。

代码语言:javascript
复制
QRgb ** finalPixels;

finalPixels = (QRgb **) (malloc(sizeof (QRgb*) * img->width() * img->height()));

    for (int x = 0; x < img->width(); ++x) {
        for (int y = 0; y < img->height(); ++y) {

            // Process pixels[y][x]


            QColor final(/* some new value */);
            QRgb finalrgb = final.rgb();

            finalPixels[y][x] = finalrgb; // What I realy want to do - Make the program fail
            finalPixels[y][x] = &finalrgb; // Don't build : invalid conversion from ‘QRgb* {aka unsigned int*}’ to ‘QRgb {aka unsigned int}’
            finalPixels[y][x] = pixels[y][x]; // Make the program fail


        }
    }

我不明白为什么不能将finalPixels[y][x]的引用更改为新的引用。变量的类型是否不正确?还是这不是怎么做的?我读了一些关于二维数组和指针的东西,但是我仍然不知道这里的问题是什么。

编辑

@rames通过建议使用pixel()setPixel()方法回答了这个问题。这些方法使用起来容易得多,但这不是我想要的。我的第一个实现是使用这些方法,但正如方法文档所说:

警告:由于调用了内部detach()函数,此函数的开销很大;如果性能问题,建议使用scanLine()直接访问像素数据。

由于我的目标是将滤波器应用到像模糊、边缘检测这样的图像中,所以我需要性能,所以这就是我尝试使用scanLine()的原因。

我试图改变我的变量类型。然后简单地改变像素的颜色如下:

代码语言:javascript
复制
QRgb * pixels[img->height()];


#pragma omp parallel 
for (int y = 0; y < img->height(); ++y)
   pixels[y] = (QRgb*) img->scanLine();
}

for (int x = 0; x < img->width(); ++x) {
  for (int y = 0; y < img->height(); ++y) {
      QColor c(0,0,0);
      QRgb cr = c.rgb();
      pixels[y][x] = cr;
  }
}

但是当程序运行pixels[y][x] = cr;时,即使这样也失败了,我不明白为什么。QtCreator的输出为he program has unexpectedly finished.

好的,我知道如何使用scanLine()方法修改图像的像素,这要感谢@user3528438和@Rames。但是,我仍然找不到一种方法来获取变量中的所有像素。我的目标是有一个临时变量,这样,我就可以用原始像素计算图像上的修改。这是我最后一次尝试:

代码语言:javascript
复制
QRgb * pixelsCopy[img->height()][img->width()];
QRgb * pColor;

for (int y = 0; y < img->height(); ++y) {
    for (int x = 0; x < img->width(); ++x) {
        pColor = new QRgb( (QRgb)img->scanLine(y)[x] );

        pixelsCopy[y][x] = pColor;
    }
}

for (int x = 0; x < img->width(); ++x) {
    for (int y = 0; y < img->height(); ++y) {
        int color =  qRed(*pixelsCopy[y][x]); // Return 0
        std::cout << "Pixel at " << x << ", " << y << " is " << color << std::endl;
    }
} 

这个编译和运行良好,但是所有的值都是0。如果我与原始像素相比,情况就不是这样了。你能向我解释为什么我的值不是原始值,并且在我的*pixelsCopy变量中都设置为0吗?而且,对于每个像素来说,调用scanLine()方法是不是太重了?我还试图将*pixelsCopy更改为pixelsCopy,但仍然得到0值。

编辑2

多亏了@user3528438和@Rames,我终于找到了一种将复制像素到一个新变量中的方法,但是我得到了奇怪的结果。我编写了一个代码,复制像素并将它们重新应用到图像中,但我没有得到相同的图像。

代码语言:javascript
复制
QRgb pixelsCopy[img->height()][img->width()];

for (int y = 0; y < img->height(); ++y) {
    QRgb * line = reinterpret_cast<QRgb *>(img->scanLine(y));
    for (int x = 0; x < img->width(); ++x) {
        pixelsCopy[y][x] = line[x];
    }
}

for (int x = 0; x < img->width(); ++x) {
    for (int y = 0; y < img->height(); ++y) {
        int r = qRed(pixelsCopy[y][x]);
        QColor final(r, r, r);
        img->scanLine(y)[x] = final.rgb();

    }
}

这就是之前和之后:

看上去像是坐标错误,但我检查了好几次,什么也没看到..如果您有一个更快的和/或更干净的方法复制原始像素,这将是很好的建议我!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-11-22 11:43:29

由于我的问题有点过于宽泛,我创建了Qt论坛的主题,而克里斯·卡瓦则准确地回答了我的问题。

将像素复制到另一个变量

代码语言:javascript
复制
int size = img->height() * img->width();
QRgb* data = new QRgb[size]; //don't forget to delete it somewhere
memmove(data, img.bits(), img.height() * img.width() * sizeof(QRgb));
// We don't need to copy each pixel, that's slow

处理每个像素

我们可以通过增加x和y来读取每个像素。

代码语言:javascript
复制
for (int y = 0; y < img->height(); ++y) {
   for (int x = 0; x < img->width(); ++x) {

但这将是缓慢的,它将更快地使用指针。

代码语言:javascript
复制
QRgb* ptr = data;
QRgb* end = ptr + img.width() * img.height();
for (; ptr < end; ++ptr)
    *ptr = qRgb(qRed(*ptr), qRed(*ptr), qRed(*ptr));

STD样式:将像素复制到另一个变量

代码语言:javascript
复制
//copy
std::vector<QRgb> pixels;
pixels.resize(img.height() * img.width());
memmove(pixels.data(), img.bits(), img.height() * img.width() * sizeof(QRgb));

STD样式:处理每个像素

代码语言:javascript
复制
std::for_each(pixels.begin(), pixels.end(), [](QRgb& c) { c = qRgb(qRed(c), qRed(c), qRed(c)); });

在c++17中,您甚至可以像这样轻松地并行和验证它:

代码语言:javascript
复制
std::for_each(std::execution::parallel_unsequenced_policy, 
              pixels.begin(), pixels.end(), [](QRgb& c) { c = qRgb(qRed(c), qRed(c), qRed(c)); });

感谢Chris的帮助,上面的所有代码都是由他在Qt论坛上创建的主题上给出的。

票数 2
EN

Stack Overflow用户

发布于 2016-11-14 22:47:00

,而不是,使用数组。QImage类是为像素操作而设计的,您确实应该使用这个类。假设img变量为QImage *类型

代码语言:javascript
复制
QImage finalImage(*img);
for (int y = 0; y < finalImage.height(); ++y) {
    QRgb *line = reinterpret_cast<QRgb*>(finalImage.scanLine(y));
    for (int x = 0; x < finalImage.width(); ++x) {
        QRgb pixelRgb = line[x];
        // Process pixelRgb

        QColor final(/* some new value */);
        line[x] = final.rgb();
    }
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40598338

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档