Revision: 6507
http://sourceforge.net/p/jump-pilot/code/6507
Author: ma15569
Date: 2020-09-22 09:26:19 +0000 (Tue, 22 Sep 2020)
Log Message:
-----------
Ported functionality from TiffUtils to TiffUtilsV2.
Make TiffUtils deprecated
Modified Paths:
--------------
core/trunk/src/org/openjump/core/rasterimage/RasterImageIO.java
core/trunk/src/org/openjump/core/rasterimage/TiffUtils.java
core/trunk/src/org/openjump/core/rasterimage/TiffUtilsV2.java
Modified: core/trunk/src/org/openjump/core/rasterimage/RasterImageIO.java
===================================================================
--- core/trunk/src/org/openjump/core/rasterimage/RasterImageIO.java
2020-09-21 13:32:21 UTC (rev 6506)
+++ core/trunk/src/org/openjump/core/rasterimage/RasterImageIO.java
2020-09-22 09:26:19 UTC (rev 6507)
@@ -26,7 +26,6 @@
import org.apache.commons.imaging.ImageReadException;
import org.apache.commons.imaging.formats.tiff.TiffField;
import org.apache.commons.imaging.formats.tiff.fieldtypes.FieldType;
-import org.openjump.core.rasterimage.TiffTags.TiffMetadata;
import com.sun.media.jai.codec.FileSeekableStream;
import com.sun.media.jai.codec.TIFFDirectory;
@@ -38,8 +37,6 @@
import com.vividsolutions.jts.geom.Envelope;
import com.vividsolutions.jump.I18N;
import com.vividsolutions.jump.workbench.WorkbenchContext;
-import com.vividsolutions.jump.workbench.imagery.ReferencedImageException;
-import com.vividsolutions.jump.workbench.imagery.geoimg.GeoReferencedRaster;
import com.vividsolutions.jump.workbench.ui.Viewport;
/**
@@ -146,7 +143,7 @@
Envelope imageEnvelope = TiffUtilsV2.getEnvelope(tiffFile);
Overviews overviews = OverviewsUtils.getOverviews(new
File(fileNameOrURL), imageEnvelope);
- return TiffUtils.readImage(tiffFile, viewPortEnvelope, requestedRes,
overviews, stats);
+ return TiffUtilsV2.readImage(tiffFile, viewPortEnvelope, requestedRes,
overviews, stats);
} else if (fileNameOrURL.toLowerCase().endsWith(".flt")) {
Modified: core/trunk/src/org/openjump/core/rasterimage/TiffUtils.java
===================================================================
--- core/trunk/src/org/openjump/core/rasterimage/TiffUtils.java 2020-09-21
13:32:21 UTC (rev 6506)
+++ core/trunk/src/org/openjump/core/rasterimage/TiffUtils.java 2020-09-22
09:26:19 UTC (rev 6507)
@@ -5,7 +5,6 @@
import java.awt.geom.NoninvertibleTransformException;
import java.awt.image.BufferedImage;
import java.awt.image.Raster;
-import java.awt.image.renderable.ParameterBlock;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
@@ -16,9 +15,7 @@
import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
-import javax.media.jai.JAI;
import javax.media.jai.RenderedOp;
-import javax.media.jai.util.ImagingListener;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
@@ -36,7 +33,10 @@
/**
*
* @author AdL
+ * @deprecated moved all methods to newer
+ * org.openjump.core.rasterimage.TiffUtilsV2 class
*/
+@Deprecated
public class TiffUtils {
public static ImageAndMetadata readImage(File tiffFile, Envelope
viewportEnvelope, Resolution requestedRes,
Modified: core/trunk/src/org/openjump/core/rasterimage/TiffUtilsV2.java
===================================================================
--- core/trunk/src/org/openjump/core/rasterimage/TiffUtilsV2.java
2020-09-21 13:32:21 UTC (rev 6506)
+++ core/trunk/src/org/openjump/core/rasterimage/TiffUtilsV2.java
2020-09-22 09:26:19 UTC (rev 6507)
@@ -1,14 +1,37 @@
package org.openjump.core.rasterimage;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.geom.NoninvertibleTransformException;
+import java.awt.image.BufferedImage;
+import java.awt.image.Raster;
import java.awt.image.renderable.ParameterBlock;
import java.io.File;
+import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import javax.imageio.ImageIO;
+import javax.imageio.ImageReadParam;
+import javax.imageio.ImageReader;
+import javax.imageio.stream.ImageInputStream;
import javax.media.jai.JAI;
import javax.media.jai.RenderedOp;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+import org.apache.commons.imaging.ImageReadException;
+import org.apache.commons.imaging.formats.tiff.TiffField;
+import org.apache.commons.imaging.formats.tiff.TiffImageMetadata;
+import org.apache.commons.imaging.formats.tiff.TiffImageParser;
+import org.xml.sax.SAXException;
+
+import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Envelope;
+import com.vividsolutions.jump.workbench.Logger;
import com.vividsolutions.jump.workbench.imagery.ReferencedImageException;
import com.vividsolutions.jump.workbench.imagery.geoimg.GeoReferencedRaster;
@@ -66,4 +89,283 @@
renderedOp = JAI.create("scale", parameterBlock);
return JAI.create("scale", parameterBlock);
}
+ public static ImageAndMetadata readImage(File tiffFile, Envelope
viewportEnvelope, Resolution requestedRes,
+ Overviews overviews, Stats stats) throws
NoninvertibleTransformException, IOException, FileNotFoundException,
+ TiffTags.TiffReadingException, Exception {
+
+ // Try to read geotiff tags
+ TiffTags.TiffMetadata tiffMetadata =
TiffTags.readMetadata(tiffFile);
+ int originalImageWidth = tiffMetadata.getColsCount();
+ int originalImageHeight = tiffMetadata.getRowsCount();
+ Resolution cellSize = tiffMetadata.getResolution();
+ Double noData = tiffMetadata.getNoData();
+
+ // Now try with tfw
+ if (cellSize == null) {
+ WorldFileHandler worldFileHandler = new
WorldFileHandler(tiffFile.getAbsolutePath(), true);
+ Envelope envelope =
worldFileHandler.readWorldFile(originalImageWidth, originalImageHeight);
+ cellSize = new Resolution(envelope.getWidth() /
originalImageWidth, envelope.getHeight() / originalImageHeight);
+ }
+
+ Envelope wholeImageEnvelope =
RasterImageIO.getGeoReferencing(tiffFile.getAbsolutePath(), true,
+ new Point(originalImageWidth, originalImageHeight));
+
+ if (requestedRes == null) {
+ requestedRes = cellSize;
+ }
+
+ int overviewLevel = overviews.pickOverviewLevel(requestedRes);
+
+ if (stats == null) {
+ // Statistics on all pixels
+ stats = calculateStats(tiffFile, noData, tiffFile);
+ }
+
+ if (overviews.getOverviewsCount() == 1) {
+
+ // No overviews, decimation (subsampling)
+
+ float xScale = (float) (cellSize.getX() / requestedRes.getX());
+ float yScale = (float) (cellSize.getY() / requestedRes.getY());
+ xScale = Math.min(xScale, 1);
+ yScale = Math.min(yScale, 1);
+
+ RenderedOp renderedOp = readSubsampled(tiffFile, xScale, yScale);
+
+ // For better looking results, but slower:
+ // rop = JAI.create("SubsampleAverage", pb);
+
+ Resolution subsetResolution = new
Resolution(wholeImageEnvelope.getWidth() / renderedOp.getWidth(),
+ wholeImageEnvelope.getHeight() / renderedOp.getHeight());
+
+ Rectangle imageSubset =
RasterImageIO.getDrawingRectangle(renderedOp.getWidth(), renderedOp.getHeight(),
+ wholeImageEnvelope, viewportEnvelope, subsetResolution);
+
+ BufferedImage bufferedImage;
+ Envelope imagePartEnvelope;
+ int actualImageWidth;
+ int actualImageHeight;
+ if (imageSubset == null) {
+ bufferedImage = null;
+ imagePartEnvelope = null;
+ actualImageWidth = 0;
+ actualImageHeight = 0;
+ } else {
+ bufferedImage = renderedOp.getAsBufferedImage(imageSubset,
null);
+ imagePartEnvelope = getImageSubsetEnvelope(wholeImageEnvelope,
imageSubset, subsetResolution);
+ actualImageWidth = bufferedImage.getWidth();
+ actualImageHeight = bufferedImage.getHeight();
+ }
+
+ Metadata metadata = new Metadata(wholeImageEnvelope,
imagePartEnvelope,
+ new Point(originalImageWidth, originalImageHeight), new
Point(actualImageWidth, actualImageHeight),
+ (cellSize.getX() + cellSize.getY()) / 2,
(subsetResolution.getX() + subsetResolution.getY()) / 2, noData,
+ stats);
+ return new ImageAndMetadata(bufferedImage, metadata);
+
+ } else {
+
+ // Read from internal overviews
+ ImageAndMetadata imageAndMetadata = readImage(tiffFile,
overviewLevel, 0,
+ new Point(originalImageWidth, originalImageHeight), cellSize,
wholeImageEnvelope, viewportEnvelope, noData,
+ stats);
+
+ // Read from external overviews
+ if (imageAndMetadata == null) {
+ File ovrFile = new File(tiffFile.getParent(),
tiffFile.getName() + ".ovr");
+ imageAndMetadata = readImage(ovrFile, overviewLevel,
overviews.getInternalOverviewsCount(),
+ new Point(originalImageWidth, originalImageHeight),
cellSize, wholeImageEnvelope, viewportEnvelope, noData,
+ stats);
+ }
+ return imageAndMetadata;
+
+ }
+
+ }
+
+ private static ImageAndMetadata readImage(File tiffFile, int
overviewIndex, int indexStart, Point originalSize,
+ Resolution originalCellSize, Envelope wholeImageEnvelope,
Envelope viewportEnvelope, double noDataValue,
+ Stats stats) throws IOException, NoninvertibleTransformException {
+
+ ImageInputStream imageInputStream =
ImageIO.createImageInputStream(tiffFile);
+ Iterator<ImageReader> iterator =
ImageIO.getImageReaders(imageInputStream);
+
+ if (iterator != null && iterator.hasNext()) {
+
+ ImageReader imageReader = iterator.next();
+ imageReader.setInput(imageInputStream);
+ for (int i = 0; i < imageReader.getNumImages(true); i++) {
+ if (i + indexStart == overviewIndex) {
+
+ Resolution subsetResolution = new
Resolution(wholeImageEnvelope.getWidth() / imageReader.getWidth(i),
+ wholeImageEnvelope.getHeight() /
imageReader.getHeight(i));
+
+ Rectangle imageSubset =
RasterImageIO.getDrawingRectangle(imageReader.getWidth(i),
imageReader.getHeight(i),
+ wholeImageEnvelope, viewportEnvelope, subsetResolution);
+
+ BufferedImage bufferedImage;
+ Envelope imagePartEnvelope;
+ int imageWidth;
+ int imageHeight;
+ if (imageSubset == null) {
+ bufferedImage = null;
+ imagePartEnvelope = null;
+ imageWidth = 0;
+ imageHeight = 0;
+ } else {
+ ImageReadParam imageReadParam = new ImageReadParam();
+ imageReadParam.setSourceRegion(imageSubset);
+ bufferedImage = imageReader.read(i, imageReadParam);
+ imagePartEnvelope =
getImageSubsetEnvelope(wholeImageEnvelope, imageSubset, subsetResolution);
+ imageWidth = bufferedImage.getWidth();
+ imageHeight = bufferedImage.getHeight();
+ }
+
+// double originalCellSize = subsetResolution.getX();
+// int cellsCount = imageReader.getWidth(i) *
imageReader.getHeight(i);
+// int sampleSize = 10000;
+// double lowResCellSize = Math.sqrt(Math.max(1,
cellsCount/(double)sampleSize)) * originalCellSize;
+
+// if(stats == null) {
+// BufferedImage statsBufferedImage =
imageReader.read(imageReader.getNumImages(true) - 1, null);
+// stats = calculateStats(statsBufferedImage,
noDataValue);
+// }
+
+ Metadata metadata = new Metadata(wholeImageEnvelope,
imagePartEnvelope, originalSize,
+ new Point(imageWidth, imageHeight),
(originalCellSize.getX() + originalCellSize.getY()) / 2,
+ (subsetResolution.getX() + subsetResolution.getY()) / 2,
noDataValue, stats);
+
+ return new ImageAndMetadata(bufferedImage, metadata);
+
+ }
+ }
+
+ }
+
+ return null;
+
+ }
+
+ private static Stats calculateStats(File tiffFile, double
noDataValue, File imageFile)
+ throws ParserConfigurationException, TransformerException,
ImageReadException, IOException, SAXException {
+
+ Stats stats = null;
+
+ // Look for internal stats tag
+ try {
+ TiffImageParser parser = new TiffImageParser();
+ TiffImageMetadata metadata = (TiffImageMetadata)
parser.getMetadata(tiffFile);
+ List<TiffField> tiffFields = metadata.getAllFields();
+ for (TiffField tiffField : tiffFields) {
+ if (tiffField.getTag() == TiffTags.TIFFTAG_GDAL_METADATA) {
+ GDALInternalMetadata gdalParser = new GDALInternalMetadata();
+ stats = gdalParser.readStatistics(tiffField.getStringValue());
+ break;
+ }
+ }
+ } catch (Exception ex) {
+ stats = null;
+ }
+
+ if (stats != null) {
+ return stats;
+ }
+
+ // Look for aux.xml file
+ File auxXmlFile = new File(imageFile.getParent(),
imageFile.getName() + ".aux.xml");
+ if (auxXmlFile.exists()) {
+ GDALPamDataset gdalPamDataset = new GDALPamDataset();
+ try {
+ stats = gdalPamDataset.readStatistics(auxXmlFile);
+ return stats;
+ } catch (Exception ex) {
+ Logger.error("Failed to read statistics.", ex);
+ return createStatsXml(tiffFile, noDataValue, auxXmlFile);
+ }
+ }
+ return createStatsXml(tiffFile, noDataValue, auxXmlFile);
+
+ }
+
+ private static Stats createStatsXml(File tiffFile, double
noDataValue, File auxXmlFile)
+ throws ParserConfigurationException, TransformerException,
TransformerConfigurationException, SAXException,
+ IOException {
+
+ BufferedImage bufferedImage = readSubsampled(tiffFile, 1,
1).getAsBufferedImage();
+ int bandCount = bufferedImage.getRaster().getNumBands();
+
+ double minValue[] = new double[bandCount];
+ double maxValue[] = new double[bandCount];
+ double sum[] = new double[bandCount];
+ double sumSquare[] = new double[bandCount];
+ long cellsCount[] = new long[bandCount];
+
+ for (int b = 0; b < bandCount; b++) {
+ minValue[b] = Double.MAX_VALUE;
+ maxValue[b] = -Double.MAX_VALUE;
+ }
+
+ for (int r = 0; r < bufferedImage.getHeight(); r++) {
+ Raster raster = bufferedImage.getData(new Rectangle(0, r,
bufferedImage.getWidth(), 1));
+ for (int c = 0; c < bufferedImage.getWidth(); c++) {
+
+ for (int b = 0; b < bandCount; b++) {
+
+ double value = raster.getSampleDouble(c, r, b);
+ if (value != noDataValue && (float) value != (float)
noDataValue && !Double.isNaN(value)
+ && !Double.isInfinite(value)) {
+ if (value < minValue[b])
+ minValue[b] = value;
+ if (value > maxValue[b])
+ maxValue[b] = value;
+ cellsCount[b]++;
+ sum[b] += value;
+ sumSquare[b] += value * value;
+ }
+
+ }
+
+ }
+ }
+
+ Stats stats = new Stats(bandCount);
+ for (int b = 0; b < bandCount; b++) {
+ double meanValue = sum[b] / cellsCount[b];
+ double stdDevValue = Math.sqrt(sumSquare[b] / cellsCount[b] -
meanValue * meanValue);
+ stats.setStatsForBand(b, minValue[b], maxValue[b], meanValue,
stdDevValue);
+ }
+
+ // Write aux.xml
+ GDALPamDataset gdalPamDataset = new GDALPamDataset();
+ gdalPamDataset.writeStatistics(auxXmlFile, stats);
+
+ return stats;
+
+ }
+
+ private static Envelope getImageSubsetEnvelope(Envelope
wholeImageEnvelope, Rectangle imageSubset,
+ Resolution subsetResolution) {
+
+ double ulX = Math.max(wholeImageEnvelope.getMinX(),
+ wholeImageEnvelope.getMinX() + imageSubset.getX() *
subsetResolution.getX());
+ double ulY = Math.min(wholeImageEnvelope.getMaxY(),
+ wholeImageEnvelope.getMaxY() - imageSubset.getY() *
subsetResolution.getY());
+ double lrX = Math.min(wholeImageEnvelope.getMaxX(),
wholeImageEnvelope.getMinX()
+ + imageSubset.getX() * subsetResolution.getX() +
imageSubset.getWidth() * subsetResolution.getX());
+ double lrY = Math.max(wholeImageEnvelope.getMinY(),
wholeImageEnvelope.getMaxY()
+ - imageSubset.getY() * subsetResolution.getY() -
imageSubset.getHeight() * subsetResolution.getY());
+ Coordinate ulCoord = new Coordinate(ulX, ulY);
+ Coordinate lrCoord = new Coordinate(lrX, lrY);
+
+ Envelope imagePartEnvelope = new Envelope(ulCoord, lrCoord);
+
+ return imagePartEnvelope;
+
+ }
+
+ public static Double readCellValue(File tiffFile, int col, int row,
int band) throws Exception {
+ Rectangle rectangle = new Rectangle(col, row, 1, 1);
+ return
getRenderedOp(tiffFile).getData(rectangle).getSampleDouble(col, row, band);
+ }
+
}
_______________________________________________
Jump-pilot-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/jump-pilot-devel