Warm tip: This article is reproduced from serverfault.com, please click

c++-使用指针设置8位灰度图像的像素颜色

(c++ - Setting pixel color of 8-bit grayscale image using pointer)

发布于 2020-11-29 16:18:30

我有以下代码:

QImage grayImage = image.convertToFormat(QImage::Format_Grayscale8);
int size = grayImage.width() * grayImage.height();
QRgb *data = new QRgb[size];
memmove(data, grayImage.constBits(), size * sizeof(QRgb));

QRgb *ptr = data;
QRgb *end = ptr + size;
for (; ptr < end; ++ptr) {
    int gray = qGray(*ptr);
}

delete[] data;

它基于此:https : //stackoverflow.com/a/40740985/8257882

如何使用该指针设置像素的颜色?

另外,使用qGray()并加载“更大”的图像似乎会使此崩溃。

这有效:

int width = image.width();
int height = image.height();
for (int y = 0; y < height; ++y) {
    for (int x = 0; x < width; ++x) {
        image.setPixel(x, y, qRgba(0, 0, 0, 255));
    }
}

但是,与显式处理图像数据相比,它的速度很慢。

编辑

好的,我现在有以下代码:

for (int y = 0; y < height; ++y) {
    uchar *line = grayImage.scanLine(y);
    for (int x = 0; x < width; ++x) {
        int gray = qGray(line[x]);
        *(line + x) = uchar(gray);
        qInfo() << gray;
    }
}

而且似乎可行。但是,当我使用仅具有黑白颜色的图像并打印灰度值时,黑色给我0,白色给我39。如何获得0-255范围内的灰度值?

Questioner
Deeds
Viewed
11
Marko Mahnič 2020-12-01 15:56:37

首先,你在此行中复制了太多数据:

memmove(data, grayImage.constBits(), size * sizeof(QRgb));

ob Qrgb的大小为4个字节,但是根据文档,Format_Grayscale8像素的大小仅为8位或1个字节。如果删除sizeof(QRgb),则应该复制正确数量的字节,并假定位图中的所有行都是连续的(根据文档,它们不是连续的,它们至少对齐32位,因此你必须占size)。数组data不应为类型,Qrgb[size]应为ucahr[size]然后,你可以根据需要进行修改data最后,你可能必须使用其中一个接受图像位uchar并将其分配给旧图像的构造函数之一来创建一个新的QImage

auto newImage = QImage( data, image.width(), image.height(), QImage::Format_Grayscale8, ...);
grayImage = std::move( newImage );

但是除了复制图像数据外,你可能还可以grayImage直接通过bits(),甚至更好地通过来访问其数据直接进行修改scanLine(),如下所示:

int line, column;
auto pLine = grayImage.scanLine(line);
*(pLine + column) = uchar(grayValue);

编辑

根据scanLine文档,图像至少32位对齐。因此,如果8位grayScale图像的宽度为3像素,则每4个字节将开始一条新的扫描线。如果你具有3x3的图像,则保存图像像素所需的内存总大小将为12。以下代码显示了所需的内存大小:

int main() {
   auto image = QImage(3, 3, QImage::Format_Grayscale8);
   std::cout << image.bytesPerLine() * image.height() << "\n";
   return 0;
}

fill方法(将所有灰度值设置为0xC0)可以这样实现:

   auto image = QImage(3, 3, QImage::Format_Grayscale8);
   uchar gray = 0xc0;
   for ( int i = 0; i < image.height(); ++i ) {
      auto pLine = image.scanLine( i );
      for ( int j = 0; j < image.width(); ++j )
         *pLine++ = gray;
   }