hey Peppe,
nice try, but no dice. the reason i created an explicit TiffUtilsV2 was
to make sure it contains no reference to RasterImageIO or TiffTags
anymore. the idea is to wrap GeoReferencedRaster functionality to reuse.
GeoReferencedRaster includes all functionality for retrieving an
Envelope or dimensions needed.
If you are lacking functionality in GeoReferencedRaster we may add it
accordingly.
i cut some code parts below and commented them which should be replaced
by using GeoReferencedRaster routines. ..ede
On 9/22/2020 11:26, jump-pilot-svn--- via Jump-pilot-devel wrote:
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
SNIP
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 @@
SNIP
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;
SNIP
@@ -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);
+ }
not needed. should be retrievable from GeoReferencedRaster
+ Envelope wholeImageEnvelope =
RasterImageIO.getGeoReferencing(tiffFile.getAbsolutePath(), true,
+ new Point(originalImageWidth, originalImageHeight));
Envelope as well.
+ if (requestedRes == null) {
+ requestedRes = cellSize;
+ }
+
+ int overviewLevel = overviews.pickOverviewLevel(requestedRes);
+
+ if (stats == null) {
+ // Statistics on all pixels
+ stats = calculateStats(tiffFile, noData, tiffFile);
+ }
+
SNIP
+ 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);
this seems to be a leftover. we want to enforce a specific TIFF reader, which
seems not to be done here.
why exactly are there two readImage() methods needed anyway? one should
suffice. can you remove it?
+ 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;
+
+ }
not sure about stats or what they actually do. we might need to extend
GeoReferencedraster in that regard.
+ 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);
+ }
+
}
this looks clean, original code. nor reference to the "old" framework :)
_______________________________________________
Jump-pilot-devel mailing list
Jump-pilot-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/jump-pilot-devel