【问题标题】:How to display this data buffer in a QImage如何在 QImage 中显示此数据缓冲区
【发布时间】:2011-07-17 15:53:42
【问题描述】:

我想在 QImage 中显示一张图片。

这是填充 rows*cols 图像的代码的 sn-p:

    rgbMapped[row][col * 3] = red;

    rgbMapped[row][col * 3 + 1] = green;

    rgbMapped[row][col * 3 + 2] = blue;

如您所见,我的数据缓冲区是“行高”并且是“列*3 宽”

rgbMapped 是一个 unsigned char** 数组。所以回到我的 QT 代码中,我有以下内容:

QImage *qi = new QImage(getWidth(), getHeight(), QImage::Format_RGB888);

for (int h = 0; h< getHeight(); h++){
    memcpy(qi->scanLine(h), rgbMapped[h], getWidth()*3);
}
QPixmap p(QPixmap::fromImage(*qi,Qt::ColorOnly));

if(scene.items().contains(item)){
    scene.removeItem(item);
}
item = new ImagePixmapItem(p);
scene.addItem(item);
ui->graphicsView->setScene(&scene);
ui->graphicsView->show();

ImagePixMapItem 是我创建的一个 QGraphicsPixmapItem,它允许我拦截一些鼠标事件,但我不会对任何绘图函数或任何东西做任何事情。

当我运行此代码时,我返回的图像看起来像我的图像,除了有三个副本,一个是绿色的,一个是黄色的,一个是明显的紫色。

如果这三个数据相互重叠,看起来可能是正确的图像?

【问题讨论】:

  • - 我会尝试简化测试用例并将图像保存到文件中,或者直接使用 QPainter 进行绘制。只是为了确保 QImage-QPixmap 转换或图形视图没有问题。 - 我的第一个猜测是行和列会以某种方式混淆。
  • 3 份,你的意思是你有 3 个相同的图像水平或垂直挤压成相同大小的图像?或者结果是预期的宽度或高度的 3 倍?
  • 它是应有的宽度的 3 倍。我认为那部分可能是因为我的 getHeight() 和 getWidth() 正在返回数组的尺寸。那应该是图像的尺寸吗?
  • 如果 getWidth() 是一个数组维度 (=3 * image-width) 上面的代码是不正确的。在“new QImage(...)”中,您应该放入 getWidth()/3,而在 memcpy(..) 中,您应该只放入 getWidth() - 而不是 getWidth()*3。我认为如果 getHeight()、getWidth() 指的是实际的图像语义而不是实现细节,它会让你的代码更清晰。在下面的回答中,我假设 getWidth() 是实际的图像宽度。
  • 是的,QImage 的宽度和高度输入是像素尺寸,而不是您的数组大小。

标签: c++ qt qt4 qgraphicsview qgraphicsitem


【解决方案1】:

只是一个假设,但从您提到的(错误)颜色来看,我怀疑问题可能出在您关于 char **rgbMapped 变量的分配/初始化代码上。 能否请您发布此代码?

我将尝试在下面编写一个可能正确(?)的初始化代码 只是给你一个可能有帮助的提示(我还没有编译代码, 因此我为任何语法错误道歉)。 我使用 malloc() 但您也可以使用 new() 运算符。

// allocate a single buffer for all image pixels
unsigned char *imgbuf = malloc(3 * getWidth() * getHeight());

// allocate row pointers
unsigned char **rgbMapped = malloc(getHeight() * sizeof (unsigned char *)); 

// Initialize row pointers
for (int h=0; h < getHeight(); h++)
{
  *rgbMapped[h] = &imgbuf[h * 3 * getWidth()];
}

// ... do your processing

// Free the image buffer & row pointers
free(imgbuf);
imgbuf = NULL;
free(rgbMapped);
rgbMapped = NULL;

重要的部分是行指针的初始化(你忘了*3吗?)。 只是我的 2c。

【讨论】:

  • 我喜欢这种方法。您可以获得可以使用括号表示法访问的连续内存块。 +1
  • 只是为了避免混淆:在上面的代码示例中,我假设 getHeight()、getWidth() 指的是实际的图像高度和宽度——而不是所需的 char 数组的宽度。另一种方法是在每个行指针上分配一个内存块,但在某些系统中它更慢并且更容易出现内存碎片情况。
【解决方案2】:

你在考虑步幅吗? 每条扫描线必须从 4 字节边界开始。 此外,它可能不是打包像素格式,因此每个像素是 4 个字节而不是 3 个

【讨论】:

  • 我不知道扫描线必须在 4 字节边界上
  • 这不是问题所在。他让 QImage 分配内存并使用其中的扫描线缓冲区。任何步幅要求都将由 QImage 代码处理。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-23
  • 2011-07-29
  • 1970-01-01
相关资源
最近更新 更多