Java实现基于GDAL将单波段影像转为三波段影像-唯一值渲染

发布时间:2024年01月09日

在处理遥感影像的渲染时,经常需要处理单波段影像。单波段影像没有任何颜色,只有一个波段的值。渲染时只能采用色带拉伸、离散颜色、唯一值渲染这几种方式。直接将单波段影像转成三波段的影像,并将三个波段转为颜色对应的rgb值,这样可以加速渲染、切片的过程。这里我有一张单波段影像,需要按照唯一值的方式,进行渲染,这里记录一下实现过程。

Java依赖

        <dependency>
            <groupId>org.gdal</groupId>
            <artifactId>gdal</artifactId>
            <version>3.5.0</version>
        </dependency>

注意我本地部署的是gdal3以上的版本,不同版本的api会有不同

实现代码

package map.tile.server.tool;

import org.gdal.gdal.Band;
import org.gdal.gdal.Dataset;
import org.gdal.gdal.Driver;
import org.gdal.gdal.gdal;
import org.gdal.gdalconst.gdalconstConstants;

import java.awt.*;

import java.util.HashMap;
import java.util.Map;

import static org.gdal.gdalconst.gdalconstConstants.GDT_Byte;

public class RasterTool {

    public static void main(String[] args) throws Exception {
        // 注册所有支持的格式
        gdal.AllRegister();

        String inputFile = "E:\\栅格\\2023_20230430.tif";
        Dataset dataset = gdal.Open(inputFile, gdalconstConstants.GA_ReadOnly);

        if (dataset == null) {
            System.out.println("无法打开输入图像");
            return;
        }

        int width = dataset.GetRasterXSize();
        int height = dataset.GetRasterYSize();
        Band band = dataset.GetRasterBand(1);
        System.out.println(band.GetRasterDataType());


        //设立每类值对应样式,样色
        Color colorLevel1 = new Color(0, 92, 230);
        Color colorLevel2 = new Color(56, 168, 0);
        Color colorLevel3 = new Color(85, 255, 0);
        Color colorLevel4 = new Color(255, 170, 0);
        Map<Short, Color> styles = new HashMap<>(4);
        styles.put((short) 1, colorLevel1);
        styles.put((short) 2, colorLevel2);
        styles.put((short) 3, colorLevel3);
        styles.put((short) 4, colorLevel4);
        // 创建新的RGB图像对象
        Double[] noDataValue = new Double[1];
        band.GetNoDataValue(noDataValue);


        Driver driver = gdal.GetDriverByName("GTiff");
        Dataset rgbDataset = driver.Create("E:\\栅格\\output_rgb_image.tif", width, height, 3, GDT_Byte);
        rgbDataset.SetProjection(dataset.GetProjection());

        rgbDataset.SetGeoTransform(dataset.GetGeoTransform());
        for (int i = 0; i < 3; ++i) {
            Band outputBand = rgbDataset.GetRasterBand(i + 1);
            outputBand.SetNoDataValue(noDataValue[0]);

            short[] buffer = new short[width];
             //            一次读取一行,防止数据溢出
            for (int j = 0; j < height; j++) {
                band.ReadRaster(0, j, width, 1, buffer);
                // 转换颜色
                processData(buffer, i + 1, styles);
                outputBand.WriteRaster(0, j, width, 1, buffer);
            }
            outputBand.FlushCache();
            outputBand.delete();
        }
        rgbDataset.FlushCache();
        rgbDataset.delete();
        dataset.delete();
    }

    private static void processData(short[] buffer, int bandIndex, Map<Short, Color> styles) {
        if (bandIndex == 1) {
            for (int i = 0; i < buffer.length; i++) {
                Color color = styles.get(buffer[i]);
                if (color != null) {
                    buffer[i] = (short) color.getRed();
                }
            }

        } else if (bandIndex == 2) {
            for (int i = 0; i < buffer.length; i++) {
                Color color = styles.get(buffer[i]);
                if (color != null) {
                    buffer[i] = (short) color.getGreen();
                }
            }
        } else if (bandIndex == 3) {
            for (int i = 0; i < buffer.length; i++) {
                Color color = styles.get(buffer[i]);
                if (color != null) {
                    buffer[i] = (short) color.getBlue();
                }
            }
        }


    }
}

效果对比

将转换后的文件,直接拖入拖入QGIS展示效果如下:

  • 转换前

转换前

  • 转换后
    转换后

注意,如果使用ArcGIS查看效果的话,需要将拉伸类型选择“无”,将应用Gamma拉伸取消勾选。

ArcGIS配置

感想

  1. GDAL的Java交互真的不太友好
  2. 太大的影像居然没有办法直接读取,整张影像读取,因为可能或超过数组的长度限制。
文章来源:https://blog.csdn.net/GISuuser/article/details/135486540
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。