cugwhp / OOPCPP

Learn C++ Programming Language

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

RSImage to QImage

cugwanghp opened this issue · comments

RSImage to QImage

Remote Sensing Image Format

CRSImage 支持3种主要的数据排列方式:

  • BSQ (Band Sequential Format)
  • BIL (Band Interleaved by Line)
  • BIP (Band Interleaved by Pixel)

为了显示图像和处理的方便,CRSImage中,将图像统一称为了三维(或二维)数组。

QImage

QImage 是用于读写绘制图像的基本类库,显示图像,我们借助于QImage,重点是如何通过图像二维数组(或三维数组)构造一个QImage对象。

以下来至于QImage构造函数QImage::QImage(uchar *data, int width, int height, QImage::Format format, QImageCleanupFunction cleanupFunction = nullptr, void *cleanupInfo = nullptr) http://doc.qt.io/qt-5/qimage.html#QImage-3

QImage::QImage(uchar *data, int width, int height, QImage::Format format, QImageCleanupFunction cleanupFunction = nullptr, void *cleanupInfo = nullptr)
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.

The buffer must remain valid throughout the life of the QImage and all copies that have not been modified or otherwise detached from the original buffer. The image does not delete the buffer at destruction. You can provide a function pointer cleanupFunction along with an extra pointer cleanupInfo that will be called when the last copy is destroyed.

If format is an indexed color format, the image color table is initially empty and must be sufficiently expanded with setColorCount() or setColorTable() before the image is used.

从构造函数中可以看出几个需要注意的地方:

    1. uchar* data 的对象需要保持持久性,即QImage图像并未深度拷贝data中的数据,仅仅只是一个指针应用。因此,构建QImage之后的,data不能delete,否则会出错。
    1. QImage::Format 在此处我们制定RGB888的格式,即图像为24位,RGB各占8位。
    1. data中的数据是如何排列的?简而言之,data中的数据是按BIP方式排列的,但有个要求,就是每一行的图像数据,要按4字节对齐。(重点在此)

RSImage2QImage

我们以代码来简单模拟图像转换的示例。

QImage CRSImage::toQImage()
{
    //1. 为QImage准备一个Buffer,而且要求具有持久性,故而最佳的办法就是定义为CRSImage的成员变量
    //unsigned char*	m_pDataBuff;	
    
    //2. 图像Buffer的大小
    int		iImageHeight = m_lLines;	//图像的宽度
    
    // 此处略有点难以理解,这是因为QImage的图像数据是按BIP方式排列的,但有个要求,就是在每一行数据排列完毕之后,数据是否为4字节的整数倍。m_lSamples是图像的宽度,*24代表,RGBRGBRGB...这样排列下来,一行图像的bit数。此时,我们要判断24*m_lSamples是否为4字节(32bit)的整数倍,比如:24*m_lSamples 为72,就要变为96.
    int		iByteLines = (m_lSamples*24+31)/32*4;    //图像每一行的字节数
    
    // m_pDataBuff 的大小为 [m_lLines*iByteLines]

    //3. 准备QImage的Buffer
    int		i, j, m=0, n;
    for (i=0; i<m_lLines; i++)	//行遍历
    {
        for (j=0; j<m_lSamples; j++)	//列遍历
        {
            m_pDataBuff[m++] = m_pppData[Red][i][j];	//R波段
            m_pDataBuff[m++] = m_pppData[Grn][i][j];	//G波段
            m_pDataBuff[m++] = m_pppData[Blu][i][j];	//B波段
        }
        
        // 1行数据填充完毕之后,我们要检查m是否为4字节的整数倍,可以写为:
        while(k%4) {k++;}	//还有一种写法 while(k%iByteLines) {k++;}
    }
    
    // 构造一个对象,返回
    return QImage(m_pDataBuff, m_lSamples, m_lLines, QImage::Format_RGB888);
}
 while(k%4) {k++;}	//还有一种写法 while(k%iByteLines) {k++;}

// 更改为
 while(m%4) {m++;}	//还有一种写法 while(k%iByteLines) {m++;}

补充一下,使用QChart要在工程.pro文件中添加如下语句:
`QT += charts //写在QT += core gui下面

target.path = $$[QT_INSTALL_EXAMPLES]/charts/barchart
INSTALLS += target//这两行写在最后即可

不写的话会出现“ undefined reference to _imp__..........”报错

老师,补充一个东西,就是在用QChart绘制图形时要在工程的.pro中添加关联相应文件的语句:
`QT += charts //写在QT += core gui下面

target.path = $$[QT_INSTALL_EXAMPLES]/charts/barchart
INSTALLS += target//这两行写在最后即可

不写的话会出现“ undefined reference to _imp__..........”报错