如何将内存图像数据封装成QImage

Posted flyinggod

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何将内存图像数据封装成QImage相关的知识,希望对你有一定的参考价值。

博客转载自:https://blog.csdn.net/lg1259156776/article/details/52318638

当采用Qt开发相机数据采集软件时,势必会遇到采集内存图像并进行处理(如缩放、旋转)操作。如果能够将内存图像数据封装成QImage,则可以利用QImage强大的图像处理功能来进行图像处理,并能很好的进行显示。下面以灰度相机为例,介绍封装方法:

第一步:首先根据相机的SDK内的读图像函数,获取图像数据imgData、宽度imgWidth和高度imHeight。
第二步:申请QImage对象,注意类型是Format_RGB32.
第三步:利用成员函数setPixel()设置QImage像素。由于相机输出的图像是灰度图像,每一位置的R、G、B分量相等且均等于当前位置的像素值。

程序如下

QImage desImage = QImage(imgWidth,imgHeight,QImage::Format_RGB32); //RGB32  
  
//RGB分量值  
int b = 0;  
int g = 0;  
int r = 0;   
  
//设置像素  
for (int i=0;i<imgHeight;i++)  
{  
    for (int j=0;j<imgWidth;j++)  
    {  
        b = (int)*(imgDataNew+i*imgWidth+j);  
        g = b;  
        r = g;  
        desImage.setPixel(j,i,qRgb(r,g,b));  
    }  
} 

对于灰度图像数据,如下封装方式是错误的。

QImage desImage = QImage(imgData, imgWidth, imgHeight, QImage::Format_Indexed8)

原因是QImage的构造函数中写道:

Constructs an image with the given width, height and format, that uses an existing memory buffer, data. The width and height must be specified in pixels,data must be 32-bit 
aligned, and each scanline of data in the image must also be 32-bit aligned.

8位灰度图封装

在内存中,8bit灰度图像的宽度有可能不能满足BMP格式需求(为4的倍数),在封装成8bit灰度QImage时,会遇到封装不完整或错误的问题。本人总结了该问题,写了一个封装内存8bit灰度图像数据的C++类

首先看代码部分:BufferToQImage.h

/*  
* Copyright (c) 2013,中科院苏州医工所  
* All rights reserved.  
*   
* 当前版本:1.0  
* 作    者:LYC 
* 完成日期:2013年6月27日  
*/  
  
#ifndef BUFFERTOQIMAGE_H  
#define BUFFERTOQIMAGE_H  
  
#include <QImage>  
#include <Windows.h>  
#include <assert.h>  
#include <QVector>  
  
class BufferToQImage  
{  
public:  
    BufferToQImage(void);  
    ~BufferToQImage(void);  
  
public:  
    QImage Pk8bitGrayToQIm(const BYTE *pBuffer, const int &bufWidth, const int &bufHight); //将8bit灰度数据封装成QImage  
  
private:  
    QVector<QRgb> vcolorTable; //生成灰度颜色表  
  
};  
  
#endif  

//BufferToQImage.cpp

/*  
* Copyright (c) 2013,中科院苏州医工所  
* All rights reserved.  
*   
* 摘    要:将内存数据封装成QImage。 
*   
* 当前版本:1.0  
* 作    者:LYC 
* 完成日期:2013年6月27日  
*/  
  
#include "BufferToQImage.h"  
  
BufferToQImage::BufferToQImage(void)  
{  
    for (int i = 0; i < 256; i++)  
    {  
        vcolorTable.append(qRgb(i, i, i));  
    }  
}  
  
BufferToQImage::~BufferToQImage(void)  
{  
  
}  
  
/* 
* 函数名:Pk8bitGrayToQIm() 
* 功能:将8bit灰度数据封装成QImage 
* 参数: 
*   pBuffer - 内存数据指针 
*   bufWidth - 内存数据宽度 
*   bufHight - 内存数据高度 
* 返回值:QImage 
* 作者:LYC 
* 时间:2013.6.27 
*/  
QImage BufferToQImage::Pk8bitGrayToQIm(const BYTE *pBuffer, const int &bufWidth, const int &bufHight)  
{  
    //对参数的有效性进行检查  
    assert((pBuffer != NULL) && (bufWidth>0) && (bufHight>0));  
  
    int biBitCount = 8; //灰度图像像素bit数  
    int lineByte = (bufWidth * biBitCount/8 + 3) / 4 * 4; //bmp行byte数(格式宽度,为4的倍数)  
  
    if (bufWidth == lineByte) //判断图像宽度与格式宽度  
    {  
        QImage qIm = QImage(pBuffer, bufWidth, bufHight, QImage::Format_Indexed8);  //封装QImage  
        qIm.setColorTable(vcolorTable); //设置颜色表  
  
        return qIm;   
    }  
    else  
    {  
        BYTE *qImageBuffer = new BYTE[lineByte * bufHight]; //分配内存空间  
        uchar *QImagePtr = qImageBuffer;  
  
        for (int i = 0; i < bufHight; i++) //Copy line by line  
        {  
            memcpy(QImagePtr, pBuffer, bufWidth);  
            QImagePtr += lineByte;  
            pBuffer += bufWidth;  
        }    
  
        QImage qImage = QImage(qImageBuffer, bufWidth, bufHight, QImage::Format_Indexed8);  //封装QImage  
        qImage.setColorTable(vcolorTable); //设置颜色表  
          
        return qImage;  
    }  
}  

利用我的博客中**任意宽度灰度BMP图像读写 V2 ** 的程序,可以读取任意宽度的图像,选择能够返回有效图像数据的成员函数,可以模拟相机写入内存中的数据。我利用rd8BitBmpNtFmt()读取78*86的图像,利用上述成员函数将内存的图像数据封装成QImage,并原尺寸显示和512*512放大显示,效果如下

技术分享图片

 


以上是关于如何将内存图像数据封装成QImage的主要内容,如果未能解决你的问题,请参考以下文章

Opencv和Qt QImage格式转Mat

qt 5 对图片解析

如何更新 QLabel 以显示 QImage

旋转QImage时如何用透明背景填充空白?

Mat与QImage互相转换

如何在Python 3中将QImage(QPixmap)转换为PIL图像?