简体   繁体   English

从 GDALDataSet 创建 RBG Color QImage

[英]create an RBG Color QImage from a GDALDataSet

I use GDAL to read some imagery files and want to display them using Qt .我使用GDAL读取一些图像文件并希望使用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.到目前为止,我设法为我的GDALDataSet每个GDALRasterBand创建了一个灰度QImage ,但我不知道如何创建单个 RGB 图像。

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 ?如何读取数据以便创建单个 RGB QImage

You are nearly there. 你快到了。 The first item is that the QImage takes a buffer with the format flag. 第一项是QImage使用带有格式标志的缓冲区。 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. 下面的示例假定一个4通道图像。

QImage Format Flag Docs: http://doc.qt.io/qt-5/qimage.html#Format-enum QImage格式标志文档: 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. 下一个组件是GDAL的RasterIO方法分别处理每个波段,这意味着您必须分别交错像素或失去逐波段加载栅格所带来的效率。

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

I like OpenCV's merge method for this. 我喜欢OpenCV的merge方法。 Just create a grayscale image for each band and merge them together. 只需为每个波段创建一个灰度图像merge它们merge在一起。

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

For example, given an RGBA GeoTiff, 例如,给定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 :没有 OpenCV,使用 msmith81886 代码:

// 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);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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