[ 
https://issues.apache.org/jira/browse/IMAGING-266?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17413674#comment-17413674
 ] 

Gary Lucas commented on IMAGING-266:
------------------------------------

Well, it took a couple of tries, but I have just submitted changes to address 
this issue. This new feature allows developers to use the Commons Imaging API 
to access the extensive set of high-resolution, global elevation data available 
through the Shuttle Radar Topography Mission (SRTM) as well as many other 
geophysical data sources.

Here's an example image produced from a TIFF file that contains elevation data 
for a 1-degree square in the vicinity of Auckland, New Zealand. The original 
TIFF file gives a 3601-by-3601 grid of elevation data points at a 1 second of 
arc spacing (about 30 meters). This image shown below is reduced to 25 percent 
of the original size.

!Imaging266_SRTM.jpg!

 

The image above was produced using a modified version of my DemoCOG 
application.  I've written a web article describing the techniques used for 
rendering numerical data from GeoTIFFs.  If you are interested, you can read it 
at [https://gwlucastrig.github.io/gridfour/notes/ElevationGeoTiff1.html]

An earlier version of the Imaging API implemented a method called 
getFloatingPointRasterData() to read data from TIFF files that contained 
floating-point data. However, the elevation data in SRTM products is stored in 
a short-integer format. So the access method has been changed to handle both 
floating-point and integral data types and its name has been changed to 
getRasterData().

The example code below shows how to use the API:
{code:java}
import java.io.File;
import org.apache.commons.imaging.FormatCompliance;
import org.apache.commons.imaging.common.bytesource.ByteSourceFile;
import org.apache.commons.imaging.formats.tiff.TiffContents;
import org.apache.commons.imaging.formats.tiff.TiffDirectory;
import org.apache.commons.imaging.formats.tiff.TiffRasterData;
import org.apache.commons.imaging.formats.tiff.TiffRasterDataType;
import org.apache.commons.imaging.formats.tiff.TiffReader;


public class ExampleRasterReader {
    public static void main(String[] args) throws Exception {
        File target = new File(args[0]);
        ByteSourceFile byteSource = new ByteSourceFile(target);

        // Establish a TiffReader. This is just a simple constructor that
        // does not actually access the file.  So the application cannot
        // obtain the byteOrder, or other details, until the contents has
        // been read.
        TiffReader tiffReader = new TiffReader(true);

        // Read the directories in the TIFF file.  Directories are the
        // main data element of a TIFF file. They usually include an image
        // element, but sometimes just carry metadata. This example
        // reads all the directories in the file.   Typically, reading
        // the directories is not a time-consuming operation.
        TiffContents contents = tiffReader.readDirectories(
                byteSource,
                true, // indicates that application should read image data, if 
present
                FormatCompliance.getDefault());

        // Read the first Image File Directory (IFD) in the file.  A practical
        // implementation could use any of the directories in the file.
        // By convention, the main payload (image or raster data) is
        // stored in the first TIFF directory with optional thumbnail images
        // or metadata directories to follow.
        TiffDirectory directory = contents.directories.get(0);

        // Check that the first directory in the file has raster data.
        if (!directory.hasTiffRasterData()) {
            System.out.println(
                    "Specified directory does not contain raster data");
            System.exit(-1);
        }

        // read all the raster data for the first directory.
        // The return value may carry short integers or single-precision
        // floating point values.  The optional parameter, which is set to
        // null in this example, could be used to fetch only a subset
        // of the overall data.
        TiffRasterData raster = directory.getRasterData(null);

        // THe data type may be integral or floating point.
        TiffRasterDataType rasterDataType = raster.getDataType();
        System.out.println("Data type for raster: " + rasterDataType.name());
        int width = raster.getWidth();
        int height = raster.getHeight();

        int nSamples = 0;
        double sumSamples = 0;
        if (rasterDataType == TiffRasterDataType.INTEGER) {
            // data type is integral, so we use getIntValue()
            for (int y = 0; y < height; y++) {
                for (int x = 0; x < width; x++) {
                    int sample = raster.getIntValue(x, y);
                    if (sample > 0) {
                        nSamples++;
                        sumSamples += sample;
                    }
                }
            }
        } else {
            // data type is floating point, so we use getValue()
            for (int y = 0; y < height; y++) {
                for (int x = 0; x < width; x++) {
                    float sample = raster.getValue(x, y);
                    if (sample > 0) {
                        nSamples++;
                        sumSamples += sample;
                    }
                }
            }
        }

        double avgSampleValue = 0;
        if (nSamples > 0) {
            avgSampleValue = sumSamples / nSamples;
        }

        System.out.println("Number of sample values > 0 is " + nSamples);
        System.out.println("Average sample value is        " + avgSampleValue);
    }
}

{code}
Finally, I'd like to thank Bruno Kinoshita for his help and excellent guidance 
in bringing this new API into the Commons Imaging code base.

> Read integer data  from GeoTIFFS
> --------------------------------
>
>                 Key: IMAGING-266
>                 URL: https://issues.apache.org/jira/browse/IMAGING-266
>             Project: Commons Imaging
>          Issue Type: New Feature
>          Components: Format: TIFF
>    Affects Versions: 1.0-alpha3
>            Reporter: Gary Lucas
>            Assignee: Bruno P. Kinoshita
>            Priority: Major
>             Fix For: 1.0-alpha3
>
>         Attachments: Imaging266_SRTM.jpg
>
>          Time Spent: 5.5h
>  Remaining Estimate: 0h
>
> I recently discovered that there is a large amount of digital elevation data 
> available in the form of 16-bit integer coded data in GeoTIFF files (TIFF 
> files with geographic tags).  I propose to enhance the Commons Imaging API to 
> read these files.  This work will be similar to the work I did for reading 
> floating-point raster data under ISSUE-251.
> Available data include the nearly-global coverage of one-second of arc 
> elevation data produced from the Shuttle Radar Topography Mission (SRTM) and 
> other sources. These products give grids of elevation data with a 30 meter 
> cell spacing for most of the world's land masses. They are available at NASA 
> Earthdata and Japan Space Systems websites, see 
> [https://asterweb.jpl.nasa.gov/gdem.asp|https://asterweb.jpl.nasa.gov/gdem.asp]
>  There is also a ocean bathymetry data set available in this format at 
> [http://www.shadedrelief.com/blue-earth/]
> This new feature will continue to expand the usefulness of the Commons 
> Imaging API in accessing GeoTIFF products.
> Request for Feedback
> So far, the data products I've found (ASTER and Blue Earth Bathymetry) give 
> elevation and ocean depth data in meters recorded as a short integer.  I 
> haven't found an example of where the 32-bit integer format is used.  For 
> now, I am planning on only coding the 16-bit integer variation.  Does anyone 
> know if the 32-bit version is worth supporting?  My criteria for determining 
> that would be based on whether there is a significant number of projects 
> using that format (life is too short to chase rarely used data formats).
> Currently, one of the code-analysis operations conducted by the Commons 
> Imaging build process is coverage by JUnit tests.  Lacking any test data for 
> the 32-bit case, I am reluctant to include it in the code base because it 
> would mean putting uncovered code into the distribution.
> Also, I am wondering about the best design for the access API.  The current 
> TiffImageParser class has a method called getFloatingPointRasterData() that 
> returns an instance of TiffRasterData.  TiffRasterData is pretty much 
> hard-wired to floating point data.  I am thinking of creating a new method 
> called getIntegerRasterData() that would return an instance of a new class 
> called TiffIntegerRasterData. Does this seem reasonable?  I considered trying 
> to combine both kinds of results into a unified class and method, but it 
> seems more unwieldy than useful. 
>  
>  



--
This message was sent by Atlassian Jira
(v8.3.4#803005)

Reply via email to