QT GDAL加载显示tif图像

1、GDAL库初始化

    // 初始化
    GDALAllRegister();
    // 设置支持中文路径和文件名
    CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "NO");

在此之前记得引用头文件

#include <gdal_priv.h> 

2、加载tiff图像文件 

void gdalLoadTiffImage()
{
    QString filePath = QFileDialog::getOpenFileName(this,
                                                    QString::fromLocal8Bit("选择图像"),
                                                    "",
                                                    QString::fromLocal8Bit("图像文件(*.tif *.tiff)"));
    if (filePath.isEmpty())
        return;

    GDALDataset *dataset = (GDALDataset *)GDALOpen(filePath.toLocal8Bit().constData(), GA_ReadOnly);
    if (!dataset) {
        // 错误处理
        return;
    }

    int width = dataset->GetRasterXSize();
    int height = dataset->GetRasterYSize();
    int bands = dataset->GetRasterCount();

    // 分配QImage的内存
    QImage::Format format = QImage::Format_RGB888;
    QImage image = QImage(width, height, format);

    // 假设我们总是处理RGB图像,并且波段顺序是红、绿、蓝
    int redBand = 1, greenBand = 2, blueBand = 3;
    if (bands == 1) {
        redBand = greenBand = blueBand = 1;
    }

    // 读取波段数据并转换为QImage
    for (int y = 0; y < height; ++y) {
        for (int x = 0; x < width; ++x) {
            uint8_t red, green, blue;

            GDALRasterBand *bandRed = dataset->GetRasterBand(redBand);
            GDALRasterBand *bandGreen = dataset->GetRasterBand(greenBand);
            GDALRasterBand *bandBlue = dataset->GetRasterBand(blueBand);

            // 像素值范围
            int success = 0;
            double minimum = bandRed->GetMinimum(&success);
            double maximum = bandRed->GetMaximum(&success);
            double noData = bandRed->GetNoDataValue(&success);

            GDALDataType dataType = bandRed->GetRasterDataType();
            switch (dataType) {
                case GDT_Byte:{
                    bandRed->RasterIO(GF_Read, x, y, 1, 1, &red, 1, 1, GDT_Byte, 0, 0);
                    bandGreen->RasterIO(GF_Read, x, y, 1, 1, &green, 1, 1, GDT_Byte, 0, 0);
                    bandBlue->RasterIO(GF_Read, x, y, 1, 1, &blue, 1, 1, GDT_Byte, 0, 0);

                    // 设置QImage的像素值
                    QRgb pixel = qRgb(red, green, blue);
                    image.setPixel(x, y, pixel);
                    break;
                } break;
                case GDT_UInt16: {
                    uint16_t red16, green16, blue16;
                    bandRed->RasterIO(GF_Read, x, y, 1, 1, &red16, 1, 1, GDT_UInt16, 0, 0);
                    bandGreen->RasterIO(GF_Read, x, y, 1, 1, &green16, 1, 1, GDT_UInt16, 0, 0);
                    bandBlue->RasterIO(GF_Read, x, y, 1, 1, &blue16, 1, 1, GDT_UInt16, 0, 0);

                    // 假设值在0-65535之间,缩放到0-255
                    red = static_cast<uint8_t>(red16 * 255.0 / 65535.0);//65535.0 -> (maximum - minimum));
                    green = static_cast<uint8_t>(green16 * 255.0 / 65535.0);
                    blue = static_cast<uint8_t>(blue16 * 255.0 / 65535.0);

                    // 设置QImage的像素值
                    QRgb pixel = qRgb(red, green, blue);
                    image.setPixel(x, y, pixel);
                    break;
                }
                case GDT_Int16: {
                    int16_t red16, green16, blue16;
                    bandRed->RasterIO(GF_Read, x, y, 1, 1, &red16, 1, 1, GDT_Int16, 0, 0);
                    bandGreen->RasterIO(GF_Read, x, y, 1, 1, &green16, 1, 1, GDT_Int16, 0, 0);
                    bandBlue->RasterIO(GF_Read, x, y, 1, 1, &blue16, 1, 1, GDT_Int16, 0, 0);

                    // 假设值在-32768到32767之间,先转换为0-65535再缩放到0-255
                    // 注意这里需要处理负数,并可能需要进行偏移和缩放
                    uint16_t redUnsigned = static_cast<uint16_t>(red16 + 32768);
                    uint16_t greenUnsigned = static_cast<uint16_t>(green16 + 32768);
                    uint16_t blueUnsigned = static_cast<uint16_t>(blue16 + 32768);

                    red = static_cast<uint8_t>(redUnsigned * 255.0 / 65535.0);
                    green = static_cast<uint8_t>(greenUnsigned * 255.0 / 65535.0);
                    blue = static_cast<uint8_t>(blueUnsigned * 255.0 / 65535.0);

                    // 设置QImage的像素值
                    QRgb pixel = qRgb(red, green, blue);
                    image.setPixel(x, y, pixel);
                    break;
                }
                case GDT_UInt32:{
                    uint32_t red32, green32, blue32;
                    bandRed->RasterIO(GF_Read, x, y, 1, 1, &red32, 1, 1, GDT_UInt32, 0, 0);
                    bandGreen->RasterIO(GF_Read, x, y, 1, 1, &green32, 1, 1, GDT_UInt32, 0, 0);
                    bandBlue->RasterIO(GF_Read, x, y, 1, 1, &blue32, 1, 1, GDT_UInt32, 0, 0);

                    // 假设值在0-4294967295之间,缩放到0-255
                    red = static_cast<uint8_t>(red32 * 255.0 / 4294967295.0);
                    green = static_cast<uint8_t>(green32 * 255.0 / 4294967295.0);
                    blue = static_cast<uint8_t>(blue32 * 255.0 / 4294967295.0);

                    // 设置QImage的像素值
                    QRgb pixel = qRgb(red, green, blue);
                    image.setPixel(x, y, pixel);
                    break;
                }
                case GDT_Int32:{
                    int32_t red32, green32, blue32;
                    bandRed->RasterIO(GF_Read, x, y, 1, 1, &red32, 1, 1, GDT_Int32, 0, 0);
                    bandGreen->RasterIO(GF_Read, x, y, 1, 1, &green32, 1, 1, GDT_Int32, 0, 0);
                    bandBlue->RasterIO(GF_Read, x, y, 1, 1, &blue32, 1, 1, GDT_Int32, 0, 0);

                    // 假设值在-2147483648到2147483647之间,先转换为0-4294967295再缩放到0-255
                    uint32_t redUnsigned = static_cast<uint32_t>(red32 + 2147483648);
                    uint32_t greenUnsigned = static_cast<uint32_t>(green32 + 2147483648);
                    uint32_t blueUnsigned = static_cast<uint32_t>(blue32 + 2147483648);

                    red = static_cast<uint8_t>(redUnsigned * 255.0 / 4294967295.0);
                    green = static_cast<uint8_t>(greenUnsigned * 255.0 / 4294967295.0);
                    blue = static_cast<uint8_t>(blueUnsigned * 255.0 / 4294967295.0);

                    // 设置QImage的像素值
                    QRgb pixel = qRgb(red, green, blue);
                    image.setPixel(x, y, pixel);
                    break;
                }
                case GDT_Float32:{
                    float redFloat, greenFloat, blueFloat;
                    bandRed->RasterIO(GF_Read, x, y, 1, 1, &redFloat, 1, 1, GDT_Float32, 0, 0);
                    bandGreen->RasterIO(GF_Read, x, y, 1, 1, &greenFloat, 1, 1, GDT_Float32, 0, 0);
                    bandBlue->RasterIO(GF_Read, x, y, 1, 1, &blueFloat, 1, 1, GDT_Float32, 0, 0);

                    // 假设值在0.0到1.0之间,直接乘以255
                    // 如果不是0.0到1.0,你需要知道数据的具体范围并进行适当的缩放
                    red = static_cast<uint8_t>(redFloat * 255.0);
                    green = static_cast<uint8_t>(greenFloat * 255.0);
                    blue = static_cast<uint8_t>(blueFloat * 255.0);

                    // 如果需要处理可能的超出范围的值
                    red = qMin(qMax((uint8_t)red, (uint8_t)0), (uint8_t)255);
                    green = std::min(std::max(green, (uint8_t)0), (uint8_t)255);
                    blue = std::min(std::max(blue, (uint8_t)0), (uint8_t)255);

                    // 设置QImage的像素值
                    QRgb pixel = qRgb(red, green, blue);
                    image.setPixel(x, y, pixel);
                    break;
                }
                case GDT_Float64:{
                    double redDouble, greenDouble, blueDouble;
                    bandRed->RasterIO(GF_Read, x, y, 1, 1, &redDouble, 1, 1, GDT_Float64, 0, 0);
                    bandGreen->RasterIO(GF_Read, x, y, 1, 1, &greenDouble, 1, 1, GDT_Float64, 0, 0);
                    bandBlue->RasterIO(GF_Read, x, y, 1, 1, &blueDouble, 1, 1, GDT_Float64, 0, 0);

                    // 假设值在0.0到1.0之间,直接乘以255
                    // 如果不是0.0到1.0,你需要知道数据的具体范围并进行适当的缩放
                    red = static_cast<uint8_t>(redDouble * 255.0);
                    green = static_cast<uint8_t>(greenDouble * 255.0);
                    blue = static_cast<uint8_t>(blueDouble * 255.0);

                    // 如果需要处理可能的超出范围的值
                    red = std::min(std::max(red, (uint8_t)0), (uint8_t)255);
                    green = std::min(std::max(green, (uint8_t)0), (uint8_t)255);
                    blue = std::min(std::max(blue, (uint8_t)0), (uint8_t)255);

                    // 设置QImage的像素值
                    QRgb pixel = qRgb(red, green, blue);
                    image.setPixel(x, y, pixel);
                    break;
                }

                // 对于复数类型(GDT_CInt16, GDT_CInt32, GDT_CFloat32, GDT_CFloat64),
                // GDAL通常不直接用于存储图像数据(如RGB),而是用于科学计算。
                case GDT_CInt16:{
                    int16_t redComplexValue[2], greenComplexValue[2], blueComplexValue[2]; // 数组中的第一个元素是实部,第二个元素是虚部
                    bandRed->RasterIO(GF_Read, x, y, 1, 1, redComplexValue, 1, 1, GDT_CInt16, 0, 0);
                    bandGreen->RasterIO(GF_Read, x, y, 1, 1, greenComplexValue, 1, 1, GDT_CInt16, 0, 0);
                    bandBlue->RasterIO(GF_Read, x, y, 1, 1, blueComplexValue, 1, 1, GDT_CInt16, 0, 0);

                    // 只使用实部,并像GDT_Int16那样处理
                    int16_t red16 = redComplexValue[0];
                    int16_t green16 = greenComplexValue[0];
                    int16_t blue16 = blueComplexValue[0];

                    // 假设值在-32768到32767之间,先转换为0-65535再缩放到0-255
                    // 注意这里需要处理负数,并可能需要进行偏移和缩放
                    uint16_t redUnsigned = static_cast<uint16_t>(red16 + 32768);
                    uint16_t greenUnsigned = static_cast<uint16_t>(green16 + 32768);
                    uint16_t blueUnsigned = static_cast<uint16_t>(blue16 + 32768);

                    red = static_cast<uint8_t>(redUnsigned * 255.0 / 65535.0);
                    green = static_cast<uint8_t>(greenUnsigned * 255.0 / 65535.0);
                    blue = static_cast<uint8_t>(blueUnsigned * 255.0 / 65535.0);

                    // 设置QImage的像素值
                    QRgb pixel = qRgb(red, green, blue);
                    image.setPixel(x, y, pixel);

                    break;
                }
                case GDT_CInt32:{
                    // 参考GDT_CInt16
                    break;
                }
                case GDT_CFloat32:{
                    // 参考GDT_CInt16
                    break;
                }
                case GDT_CFloat64:{
                    // 参考GDT_CInt16
                    break;
                }
            }
        }
    }

    GDALClose(dataset);
}

3、GDAL库资源释放

GDALDestroyDriverManager();

在QT安装路径下有个tif文件目录可供测试使用:C:\Qt\Qt5.15.2\5.15.2\Src\qtimageformats\tests\shared\images\tiff

按照常理来说,如果波段为1,数据类型是GDT_Byte,数据范围正常来说应该是0~255,最终显示出来的图像是灰度图,但是如下图片的数据范围却为0~65535,用自己代码显示当然也是灰度图像,但是用其它工具软件显示确实彩色图像(如PS),究竟是哪里出了问题,有待日后去研究了!!!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值