1.配置maven
<properties>
<java.version>1.8</java.version>
<geotools.version>28.0</geotools.version>
</properties>
<dependencies>
<!--必须,内置了基础的地理坐标系 不配置会导致读写tiff时找不到坐标系-->
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-epsg-hsql</artifactId>
<version>${geotools.version}</version>
</dependency>
<!--必须,读写tiff的具体api-->
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-geotiff</artifactId>
<version>${geotools.version}</version>
</dependency>
</dependencies>
<repositories>
<!--必须 geotools依赖的仓库, 常用的仓库中无geotools依赖-->
<repository>
<id>osgeo</id>
<name>OSGeo Release Repository</name>
<url>https://repo.osgeo.org/repository/release/</url>
<snapshots><enabled>false</enabled></snapshots>
<releases><enabled>true</enabled></releases>
</repository>
</repositories>
2.生成tiff文件
public static String tiffWrite() throws FactoryException, IOException {
int[][] matrix = new int[256][256];
Random r = new Random();
for (int i = 0; i < matrix.length; i++) {
int[] row = matrix[i];
for (int j = 0; j < row.length; j++) {
matrix[i][j] = Math.abs(r.nextInt() % Byte.MAX_VALUE);
//System.out.println(i + "," + j + "," + matrix[i][j]);
}
}
double tile = 6378137 * 2 * Math.PI / (1 << 16);
Envelope2D envelope = new Envelope2D( CRS.decode("EPSG:3857"),12923543.888468, 4852595.145082 - tile, tile, tile);
WritableRaster raster = createWritableRaster(4);
addBound(matrix, raster, 0);
addBound(matrix, raster, 1);
addBound(matrix, raster, 2);
addBound(matrix, raster, 3);
GridCoverageFactory f = new GridCoverageFactory();
GridCoverage2D coverage = f.create("tiffTest", raster, envelope);
GeoTiffFormat format = new GeoTiffFormat();
/*ByteArrayOutputStream bao = new ByteArrayOutputStream();
ImageOutputStream ios = ImageIO.createImageOutputStream(bao);
GridCoverageWriter writer = format.getWriter(ios);*/
File out = new File("/Users/didi/Desktop/data/test4.tiff");
GridCoverageWriter writer = format.getWriter(out);
writer.write(coverage, createWriteParameters());
writer.dispose();
coverage.dispose(true);
return "test";
}
public static WritableRaster createWritableRaster(int boundNum) {
WritableRaster raster = RasterFactory.createBandedRaster(2, 256, 256, boundNum, (Point) null);
return raster;
}
public static void addBound(int[][] matrix, WritableRaster raster, int boundIndex) {
for (int i = 0; i < 256; i++) {
for (int j = 0; j < 256; j++) {
raster.setSample(i, j, boundIndex, matrix[i][j]);
}
}
}
public static GeneralParameterValue[] createWriteParameters() {
GeoTiffFormat format = new GeoTiffFormat();
GeoTiffWriteParams wp = new GeoTiffWriteParams();
wp.setCompressionMode(GeoTiffWriteParams.MODE_EXPLICIT);
wp.setCompressionType("Deflate");
ParameterValueGroup params = format.getWriteParameters();
params.parameter(AbstractGridFormat.GEOTOOLS_WRITE_PARAMS.getName().toString()).setValue(wp);
GeneralParameterValue[] writeParameters = params.values().toArray(new GeneralParameterValue[1]);
return writeParameters;
}
3.读取tiff文件 并重新写入
public static void tiffRead(byte[] tiff) throws IOException, FactoryException {
ByteArrayInputStream arrayInputStream = new ByteArrayInputStream(tiff);
ImageInputStream stream = ImageIO.createImageInputStream(arrayInputStream);
GeoTiffReader reader = new GeoTiffReader(stream);
GridCoverage2D coverage = reader.read(null);
Envelope2D envelope = coverage.getEnvelope2D();
RenderedImage image = coverage.getRenderedImage();
double height = envelope.getHeight();
double width = envelope.getWidth();
double minx = envelope.getMinX();
double miny = envelope.getMinY();
String crs = CRS.toSRS(envelope.getCoordinateReferenceSystem());
int type = image.getSampleModel().getDataType();
int bandNum = image.getSampleModel().getNumBands();
int matrixW = image.getWidth();
//int matrixW2 = image.getTileWidth();
int matrixH = image.getHeight();
//int matrixH2 = image.getTileHeight();
int[][][] matrix = new int[bandNum][matrixW][matrixH];
Raster raster = image.getData();
for (int b = 0; b < bandNum; b++) {
for (int i = 0; i < matrixW; i++) {
for (int j = 0; j < matrixH; j++) {
int value = raster.getSample(i, j, b);
matrix[b][i][j] = value;
if (value > 0){
System.out.println(i + "," + j + "," + b + "," + value);
}
}
}
}
//tiffWrite2(crs,minx,miny,width,height,type,bandNum,matrixW,matrixH,matrix);
tiffWrite3(coverage);
}
public static void tiffWrite3(GridCoverage2D coverage) throws IOException {
File out2 = new File("/Users/didi/Desktop/data/"+ UUID.randomUUID().toString().substring(0,4)+".tiff");
GeoTiffFormat format = new GeoTiffFormat();
GridCoverageWriter writer2 = format.getWriter(out2);
writer2.write(coverage, createWriteParameters());
writer2.dispose();
coverage.dispose(true);
}
geotools版本问题,尽量使用高版本(推荐28.0,不建议使用30.0 因为需要jdk版本大于11)低版本geotools生成的tiff文件会存在以下问题
- 低版本geotools 读取时不能使用 ImageInputStream 必须要新建feil文件才能完成读取,读取的coverage重新写成tiff qgis看不到band(原因未确定,可能是colormodel的问题)
- 高版本geotools读取低版本geotools的产出tiff时 band只要大于3就会出现异常,原因是高版本的geotool默认创建的colorModel只有3个band 与raster的band数无法匹配