简体   繁体   中英

create an RBG Color QImage from a GDALDataSet

I use GDAL to read some imagery files and want to display them using Qt . So far I managed to create a gray scale QImage for each GDALRasterBand in my GDALDataSet , but I don't know how to create a single RGB image.

Here's what I've done :

#include <gdal_priv.h>
#include <QtGui\QImage>

int main(int argc, char *argv[])
{
    GDALAllRegister();

    GDALDataset* dataset = static_cast<GDALDataset*>(GDALOpen("path_to_some_image.tif", GA_ReadOnly));
    int size_out = 200;

    for (int i = 1; i <= 3; ++i)
    { 
        GDALRasterBand* band = dataset->GetRasterBand(i);

        std::vector<uchar> band_data(size_out * size_out);
        band->RasterIO(GF_Read, 0, 0, size_out, size_out, band_data.data(), size_out, size_out, GDT_Byte, 0, 0);

        QImage band_image(band_data.data(), size_out, size_out, QImage::Format_Grayscale8);
        band_image.save(QString("C:\\band_%1.png").arg(i));
    }

    return 0;
}

How do I read the data so I can create a single RGB QImage ?

You are nearly there. The first item is that the QImage takes a buffer with the format flag. As a result, that format flag needs to either match the image you are loading from file, or else needs to be transformed. The example below assumes a 4-channel image.

QImage Format Flag Docs: http://doc.qt.io/qt-5/qimage.html#Format-enum

The next component is that GDAL's RasterIO method handles each band separately, meaning you have to interleave the pixels separately or lose the efficiency that comes with loading the raster band-by-band.

RasterIO: http://gdal.org/classGDALRasterBand.html#a30786c81246455321e96d73047b8edf1

I like OpenCV's merge method for this. Just create a grayscale image for each band and merge them together.

OpenCV Merge: http://docs.opencv.org/3.0.0/d2/de8/group__core__array.html#ga61f2f2bde4a0a0154b2333ea504fab1d

For example, given an RGBA GeoTiff,

// OpenCV Libraries
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>

// GDAL Libraries
#include <gdal.h>

// QT Libraries
#include <QtGui\QImage>

using namespace cv;


int main( int argc, char* argv[] )
{

    // Initialize GDAL
    GDALAllRegister();

    // Load image
    GDALDataset* dataset = GDALOpen("path_to_some_image.tif", GA_ReadOnly);

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

    // Create each separate image as grayscale
    std::vector<cv::Mat> image_list(channels, cv::Mat( rows, cols, CV_8UC1 ));
    cv::Mat output_image;

    // Iterate over each channel
    for (int i = 1; i <= channels; ++i)
    { 
        // Fetch the band
        GDALRasterBand* band = dataset->GetRasterBand(i);

        // Read the data
        band->RasterIO( GF_Read, 0, 0, 
                        cols, rows, 
                        image_list[i-1].data, 
                        cols, rows, 
                        GDT_Byte, 0, 0);

    }

    // Merge images
    cv::merge( image_list, output_image );

    // Create the QImage
    QImage qt_image( band_data.data(), 
                     cols, 
                     rows,
                     QImage::Format_RGBA8888);

    // Do some stuff with the image

    return 0;
 }

Without OpenCV, using msmith81886 code :

// Load image
    GDALDataset* dataset = static_cast<GDALDataset*>(GDALOpen(tifFile.toLocal8Bit().data(), GA_ReadOnly));

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

    std::vector<std::vector<uchar>> bandData(channels);
    for (auto& mat : bandData)
    {
        mat.resize(size_t(rows * cols));
    }
    std::vector<uchar> outputImage(size_t(4 * rows * cols));

    // Iterate over each channel
    for (int i = 1; i <= channels; ++i)
    {
        // Fetch the band
        GDALRasterBand* band = dataset->GetRasterBand(i);

        // Read the data
        band->RasterIO(GF_Read, 0, 0, cols, rows, bandData[size_t(i - 1)].data(),
            cols, rows, GDT_Byte, 0, 0);        
    }

    for (size_t i = 0, j = 0; i < outputImage.size(); i += 4, j += 1)
    {
        outputImage[i] = bandData[0][j];
        outputImage[i + 1] = bandData[1][j];
        outputImage[i + 2] = bandData[2][j];
        outputImage[i + 3] = bandData[3][j];
    }

    // Create the QImage (or even a QPixmap suitable for displaying teh image
    QImage qtImage(outputImage.data(), cols, rows, QImage::Format_RGBA8888);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM