Предположим, я вручную созданы значения пикселей для более 4 полос, и я хочу, чтобы хранить их в Tiff файл.Как сохранить массив пикселей с более чем 4 группами в файл Tiff/GeoTiff в java?
Эти полосы могут быть для R, G, B, температуры (значения температуры не находятся в диапазоне от 0 до 255, поэтому я использую int вместо байта для pexils) и т. Д. Т.е. любую информацию, которая может берутся со спутника
Теперь я хочу сохранить эти пиксели в файл tiff. В java есть класс BufferedImage, который имеет много типов, таких как: TYPE_4BYTE_ABGR, TYPE_BYTE_GRAY и т. Д. Однако ни один из них для нескольких диапазонов более 4 диапазонов. Существует TYPE_CUSTOM, но при указании его и попытке сохранить данные в Tiff-файле он дает вам исключение, потому что он не поддерживается для операции записи (только для операции чтения, т. Е. Он может читать файл и задавать тип TYPE_CUSTOM, если он не понял тип, но он не может записать файл в непонятном типе).
Приведенный ниже код работал на 3 полосы даже не правильно (он не показывает цветное изображение, и оно выглядело как искаженное изображение с отсутствующими линиями) , но для более чем 4-х полос, как я могу это сделать?
ImageOutputStream ios = ImageIO.createImageOutputStream(os);
Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName("tiff");
ImageWriter writer = writers.next();
writer.setOutput(ios);
int index = 0;
int[] pixels = new int[width*height*numberOfBands];
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
for (int k = 0; k < numberOfBands; k++) {
pixels[index++] = //any values;
}
}
}
DataBuffer dataBuffer = new DataBufferInt(pixels, pixels.length);
// Create Raster
WritableRaster writableRaster = Raster.createBandedRaster
(dataBuffer, width, height,
width, // scanlineStride
new int[numberOfBands], // bankIndices,
new int[numberOfBands], // bandOffsets,
null); // location
// Create the image
BufferedImage bufferedImage = new BufferedImage
(width, height, BufferedImage.TYPE_BYTE_RGB);
bufferedImage.setData(writableRaster);
IIOImage iioImage = new IIOImage(bufferedImage, null, null);
ImageWriteParam param = writer.getDefaultWriteParam();
writer.write(null, iioImage, param);
Я использую GeoTools кстати
Отредактировано: Согласно @iant Я изменил код, но он дает только чистый прозрачный фон, даже я сохранил такое же количество полос, т.е. 3 полосы. @iant Не могли бы вы проверить код ниже.
package examples;
import java.awt.image.WritableRaster;
import java.io.File;
import java.io.IOException;
import javax.media.jai.RasterFactory;
import org.geotools.coverage.CoverageFactoryFinder;
import org.geotools.coverage.grid.GridCoordinates2D;
import org.geotools.coverage.grid.GridCoverage2D;
import org.geotools.coverage.grid.GridCoverageFactory;
import org.geotools.coverage.grid.GridEnvelope2D;
import org.geotools.coverage.grid.GridGeometry2D;
import org.geotools.coverage.grid.io.AbstractGridFormat;
import org.geotools.coverage.grid.io.OverviewPolicy;
import org.geotools.gce.geotiff.GeoTiffFormat;
import org.geotools.gce.geotiff.GeoTiffReader;
import org.opengis.coverage.grid.GridCoverageWriter;
import org.opengis.parameter.GeneralParameterValue;
import org.opengis.parameter.ParameterValue;
public class CreateTiffImageTest2 {
public static void main(String[] args) throws IOException {
File file = new File("/home/mosab/Desktop/input/tif.tif");
ParameterValue<OverviewPolicy> policy = AbstractGridFormat.OVERVIEW_POLICY.createValue();
policy.setValue(OverviewPolicy.IGNORE);
ParameterValue<String> gridsize = AbstractGridFormat.SUGGESTED_TILE_SIZE.createValue();
ParameterValue<Boolean> useJaiRead = AbstractGridFormat.USE_JAI_IMAGEREAD.createValue();
useJaiRead.setValue(true);
GeoTiffReader geoTiffReader = new GeoTiffReader(file);
GridCoverage2D cov = geoTiffReader.read(new GeneralParameterValue[] { policy, gridsize, useJaiRead });
GridGeometry2D geometry = cov.getGridGeometry();
GridEnvelope2D gridEnvelope = geometry.getGridRange2D();
int w = (int) gridEnvelope.getWidth();
int h = (int) gridEnvelope.getHeight();
WritableRaster writableRaster = RasterFactory.createBandedRaster(java.awt.image.DataBuffer.TYPE_DOUBLE, w, h, 3,
null);
double[] data = new double[3];
double[] dest = new double[3];
for (int i = 0; i < w; i++) {
for (int j = 0; j < h; j++) {
GridCoordinates2D coord = new GridCoordinates2D(i, j);
cov.evaluate(coord, dest);
data[0] = dest[0];
data[1] = dest[1];
data[2] = dest[2];
writableRaster.setPixel(i, j, data);
}
float perc = 100.0f * i/w;
if (i % 100 == 0) {
System.out.println("done " + perc);
}
}
// Wrap the raster as a Coverage
GridCoverageFactory factory = CoverageFactoryFinder.getGridCoverageFactory(null);
GridCoverage2D gc = factory.create("name", writableRaster, cov.getEnvelope());
File out = new File("/home/mosab/Desktop/input/tifgen.tif");
GeoTiffFormat format = new GeoTiffFormat();
GridCoverageWriter writer = format.getWriter(out);
try {
writer.write(gc, null);
writer.dispose();
} catch (IllegalArgumentException | IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Обновление 2:
import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.media.jai.RasterFactory;
import org.geotools.coverage.CoverageFactoryFinder;
import org.geotools.coverage.grid.GridCoverage2D;
import org.geotools.coverage.grid.GridCoverageFactory;
import org.geotools.coverage.grid.io.AbstractGridFormat;
import org.geotools.coverage.grid.io.GridFormatFinder;
import org.geotools.factory.Hints;
import org.geotools.gce.geotiff.GeoTiffFormat;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.referencing.CRS;
import org.opengis.coverage.grid.GridCoverageWriter;
import org.opengis.geometry.MismatchedDimensionException;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.NoSuchAuthorityCodeException;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
public class Test2 {
public static void print(Object o) {
System.out.println(o);
}
public static void main(String[] args)
throws MismatchedDimensionException, NoSuchAuthorityCodeException, FactoryException, IOException {
File out = new File("/home/mosab/Desktop/input/1.tif");
BufferedImage img = ImageIO.read(out);
// ColorModel colorModel = img.getColorModel(
WritableRaster raster = img.getRaster();
int w = img.getWidth();
int h = img.getHeight();
print("width = " + w);
print("heigh = " + h);
int numBands = raster.getNumBands();
WritableRaster writableRaster = RasterFactory.createBandedRaster(java.awt.image.DataBuffer.TYPE_INT, w, h, 3,
null);
//as I said pixels are created manually but I used here pixels from an image to check the approach
int[] data = new int[3];
for (int i = 0; i < w; i++) {
for (int j = 0; j < h; j++) {
for (int k = 0; k < numBands; k++) {
data[k] = raster.getSample(i, j, k);
}
writableRaster.setPixel(i, j, data);
}
}
GridCoverageFactory factory = CoverageFactoryFinder.getGridCoverageFactory(null);
CoordinateReferenceSystem crs = CRS.decode("EPSG:27700");
int llx = 500000;
int lly = 105000;
ReferencedEnvelope referencedEnvelope = new ReferencedEnvelope(llx, llx + (w * 10), lly, lly + (h * 10), crs);
GridCoverage2D gc = factory.create("name", writableRaster, referencedEnvelope);
AbstractGridFormat format = GridFormatFinder.findFormat(out);
Hints hints = null;
if (format instanceof GeoTiffFormat) {
hints = new Hints(Hints.FORCE_LONGITUDE_FIRST_AXIS_ORDER, Boolean.TRUE);
}
File out1 = new File("/home/mosab/Desktop/input/tifgen.tif");
GridCoverageWriter writer = format.getWriter(out1);
try {
writer.write(gc, null);
writer.dispose();
} catch (IllegalArgumentException | IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Примечание: Я использовал тип Int и массив размером 3, поскольку исходное изображение имеет RGB полосы ,
Если у вас есть особые требования, вы можете подумать о наличии собственного формата файла. – Piglet
Я бы поработал над тем, чтобы он работал с 3 полосами, прежде чем попробовать 4 –
@Piglet это можно сделать с использованием формата TIff/Geotiff, потому что он предназначен для этого. И, кстати, я упомянул ранее более 4-х полос, потому что в случае 4-го программного обеспечения это будет считать ARGB, т. Е. + Aplha. –