GDAL loads QImage

GDAL is loaded into the Qt project and displayed to the UI through QImage

Note: This article is a success through my continuous exploration and access to relevant knowledge experiments. If there is anything wrong, please let me know: [email protected]

1. Development environment:
1. opencv 3.4.1 msvc
2, GDAL 2.1 msvc
3, Qt 5.10.1
Remarks: Both opencv and gdal use the msvc compiler, and the mingw compilation environment is also available, you need to configure it yourself.

2. Development process:
1. First load a picture through GDAL;
2. Store the band information of the picture into the buffer;
3. Assign the buffer to the Mat in OpenCV; (The advantage of this step is to use opencv As an intermediate exchange layer, it can convert the picture to QImage)
4. Remix the acquired information of each band;
5. Convert the Mat of opencv to QImage;
6. Display the QImage.

3. Remarks:
This code requires you to configure your opencv and GDAL environment first. If not, please configure it yourself.

Fourth, the code:
According to the process of the second step, the code is as follows:

bool Dataset2QImage(const QString filePath,QImage &img)
{
    //1、check the file format
    QStringList formatStr;
    formatStr.append(".png");
    formatStr.append(".jpg");
    formatStr.append(".tif");
    formatStr.append(".spe");//myself define format
    formatStr.append(".bmp");

    bool format_flag=FALSE;
    for(int i=0;i<formatStr.size();i++)
    {
        if(filePath.endsWith(formatStr[i]))
        {
            format_flag=TRUE;
           break;
        }
    }

    if(!format_flag)
        return FALSE;

    // 2、Initialize GDAL
    GDALAllRegister();

    // 3、Load image
    GDALDataset* dataset = (GDALDataset *)GDALOpen(filePath.toStdString().c_str(), GA_ReadOnly);

    // 4、Get raster image size
    int rows = dataset->GetRasterYSize();
    int cols = dataset->GetRasterXSize();
    int channels = dataset->GetRasterCount();

    Mat R(rows, cols, CV_8UC1, Scalar(0));//to save R img
    Mat G(rows, cols, CV_8UC1, Scalar(0));//to save G img
    Mat B(rows, cols, CV_8UC1, Scalar(0));//to save B img
    vector<Mat> RGB(channels,cv::Mat( rows, cols, CV_8UC3,Scalar(0)));//create RGB channels

    //to init default channel
    //Mat hideChannel(rows, cols, CV_8UC1, Scalar(0));//set need hide channel color is black

    cv::Mat output_image;
    // 6、get data
    // Fetch the band 1
    GDALRasterBand* band = dataset->GetRasterBand(1);
    // Read the band 1 data
    band->RasterIO( GF_Read, 0, 0, cols, rows, B.data,
            cols, rows,GDT_Byte, 0, 0);

    // Fetch the band 2
    band = dataset->GetRasterBand(2);
    // Read the band 2 data
    band->RasterIO( GF_Read, 0, 0, cols, rows, G.data,
            cols, rows,GDT_Byte, 0, 0);

    // Fetch the band 3
    band = dataset->GetRasterBand(3);
    // Read the band 3 data
    band->RasterIO( GF_Read, 0, 0, cols, rows, R.data,
            cols, rows,GDT_Byte, 0, 0);

    // 7、set R G B value to vector mat
    RGB[0]=R;
    RGB[1]=G;
    RGB[2]=B;

    // 8、Merge images,合并通道数据
    cv::merge( RGB, output_image );

    //opencv window show the merge channels image
    //imshow("RGB",output_image);

    // 9、Create the QImage
    return Mat2QImage(output_image,img);
}

Notes on the above code:
1. In the above code, the first step is to check the format of the file, including the image format defined by myself. This depends on each person's performance. It is not rigorous, and the strictly prohibited writing method should be in the form of a filter;
2. When obtaining the data of each band through GDAL, use the specified band to obtain it. According to the optimization, it should be written in a for loop. However, after numerous experiments by myself, the mixed for loop is used. The picture is gray and white, the original image cannot be restored, I don't know why, I have tried for a long time, and the optimization here is left for later thinking.
3. In this code, the conversion of Mat to QImage is also used at the end. The specific code is as follows:

bool Mat2QImage(const Mat &mat,QImage &img)
{
    // 8-bits unsigned, NO. OF CHANNELS = 1
    if(mat.type() == CV_8UC1)
    {
        //qDebug() << "CV_8UC1";
        QImage image(mat.cols, mat.rows, QImage::Format_Indexed8);
        // Set the color table (used to translate colour indexes to qRgb values)
        image.setColorCount(256);
        for(int i = 0; i < 256; i++)
        {
            image.setColor(i, qRgb(i, i, i));
        }
        // Copy input Mat
        uchar *pSrc = mat.data;
        for(int row = 0; row < mat.rows; row ++)
        {
            uchar *pDest = image.scanLine(row);
            memcpy(pDest, pSrc, mat.cols);
            pSrc += mat.step;
        }
        img=image;
        return TRUE;
    }
    // 8-bits unsigned, NO. OF CHANNELS = 3
    else if(mat.type() == CV_8UC3)
    {
        //qDebug() << "CV_8UC3";
        // Copy input Mat
        const uchar *pSrc = (const uchar*)mat.data;
        // Create QImage with same dimensions as input Mat
        QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_RGB888);
        img = image.rgbSwapped();
        return TRUE;
    }
    else if(mat.type() == CV_8UC4)
    {
        //qDebug() << "CV_8UC4";
        // Copy input Mat
        const uchar *pSrc = (const uchar*)mat.data;
        // Create QImage with same dimensions as input Mat
        QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_ARGB32);
        img = image.copy();
        return TRUE;
    }
    else
    {
        qDebug() << "ERROR: Mat could not be converted to QImage.";
        return FALSE;
    }
}

Here is my source file, download and import your project, and then call the corresponding function.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324517251&siteId=291194637