> list = new ArrayList<>();
list.add(
new Parameter<>(
"image",
File.class,
"Image",
"GeoTiff or World+Image to display as basemap",
new KVP(Parameter.EXT, "tif", Parameter.EXT, "jpg")));
list.add(
new Parameter<>(
"shape",
File.class,
"Shapefile",
"Shapefile contents to display",
new KVP(Parameter.EXT, "shp")));
JParameterListWizard wizard =
new JParameterListWizard("Image Lab", "Fill in the following layers", list);
int finish = wizard.showModalDialog();
if (finish != JWizard.FINISH) {
System.exit(0);
}
File imageFile = (File) wizard.getConnectionParameters().get("image");
File shapeFile = (File) wizard.getConnectionParameters().get("shape");
displayLayers(imageFile, shapeFile);
}
// docs end get layers
// docs start display layers
/**
* Displays a GeoTIFF file overlaid with a Shapefile
*
* @param rasterFile the GeoTIFF file
* @param shpFile the Shapefile
*/
private void displayLayers(File rasterFile, File shpFile) throws Exception {
AbstractGridFormat format = GridFormatFinder.findFormat(rasterFile);
// this is a bit hacky but does make more geotiffs work
Hints hints = new Hints();
if (format instanceof GeoTiffFormat) {
hints = new Hints(Hints.FORCE_LONGITUDE_FIRST_AXIS_ORDER, Boolean.TRUE);
}
reader = format.getReader(rasterFile, hints);
// Initially display the raster in greyscale using the
// data from the first image band
Style rasterStyle = createGreyscaleStyle(1);
// Connect to the shapefile
FileDataStore dataStore = FileDataStoreFinder.getDataStore(shpFile);
SimpleFeatureSource shapefileSource = dataStore.getFeatureSource();
// Create a basic style with yellow lines and no fill
Style shpStyle = SLD.createPolygonStyle(Color.YELLOW, null, 0.0f);
// Set up a MapContent with the two layers
final MapContent map = new MapContent();
map.setTitle("ImageLab");
Layer rasterLayer = new GridReaderLayer(reader, rasterStyle);
map.addLayer(rasterLayer);
Layer shpLayer = new FeatureLayer(shapefileSource, shpStyle);
map.addLayer(shpLayer);
// Create a JMapFrame with a menu to choose the display style for the
frame = new JMapFrame(map);
frame.setSize(800, 600);
frame.enableStatusBar(true);
// frame.enableTool(JMapFrame.Tool.ZOOM, JMapFrame.Tool.PAN, JMapFrame.Tool.RESET);
frame.enableToolBar(true);
JMenuBar menuBar = new JMenuBar();
frame.setJMenuBar(menuBar);
JMenu menu = new JMenu("Raster");
menuBar.add(menu);
menu.add(
new SafeAction("Grayscale display") {
public void action(ActionEvent e) throws Throwable {
Style style = createGreyscaleStyle();
if (style != null) {
((StyleLayer) map.layers().get(0)).setStyle(style);
frame.repaint();
}
}
});
menu.add(
new SafeAction("RGB display") {
public void action(ActionEvent e) throws Throwable {
Style style = createRGBStyle();
if (style != null) {
((StyleLayer) map.layers().get(0)).setStyle(style);
frame.repaint();
}
}
});
// Finally display the map frame.
// When it is closed the app will exit.
frame.setVisible(true);
}
// docs end display layers
// docs start create greyscale style
/**
* Create a Style to display a selected band of the GeoTIFF image as a greyscale layer
*
* @return a new Style instance to render the image in greyscale
*/
private Style createGreyscaleStyle() {
GridCoverage2D cov = null;
try {
cov = reader.read(null);
} catch (IOException giveUp) {
throw new RuntimeException(giveUp);
}
int numBands = cov.getNumSampleDimensions();
Integer[] bandNumbers = new Integer[numBands];
for (int i = 0; i < numBands; i++) {
bandNumbers[i] = i + 1;
}
Object selection =
JOptionPane.showInputDialog(
frame,
"Band to use for greyscale display",
"Select an image band",
JOptionPane.QUESTION_MESSAGE,
null,
bandNumbers,
1);
if (selection != null) {
int band = ((Number) selection).intValue();
return createGreyscaleStyle(band);
}
return null;
}
/**
* Create a Style to display the specified band of the GeoTIFF image as a greyscale layer.
*
* This method is a helper for createGreyScale() and is also called directly by the
* displayLayers() method when the application first starts.
*
* @param band the image band to use for the greyscale display
* @return a new Style instance to render the image in greyscale
*/
private Style createGreyscaleStyle(int band) {
ContrastEnhancement ce = sf.contrastEnhancement(ff.literal(1.0), ContrastMethod.NORMALIZE);
SelectedChannelType sct = sf.createSelectedChannelType(String.valueOf(band), ce);
RasterSymbolizer sym = sf.getDefaultRasterSymbolizer();
ChannelSelection sel = sf.channelSelection(sct);
sym.setChannelSelection(sel);
return SLD.wrapSymbolizers(sym);
}
// docs end create greyscale style
// docs start create rgb style
/**
* This method examines the names of the sample dimensions in the provided coverage looking for
* "red...", "green..." and "blue..." (case insensitive match). If these names are not found it
* uses bands 1, 2, and 3 for the red, green and blue channels. It then sets up a raster
* symbolizer and returns this wrapped in a Style.
*
* @return a new Style object containing a raster symbolizer set up for RGB image
*/
private Style createRGBStyle() {
GridCoverage2D cov = null;
try {
cov = reader.read(null);
} catch (IOException giveUp) {
throw new RuntimeException(giveUp);
}
// We need at least three bands to create an RGB style
int numBands = cov.getNumSampleDimensions();
if (numBands < 3) {
return null;
}
// Get the names of the bands
String[] sampleDimensionNames = new String[numBands];
for (int i = 0; i < numBands; i++) {
GridSampleDimension dim = cov.getSampleDimension(i);
sampleDimensionNames[i] = dim.getDescription().toString();
}
final int RED = 0, GREEN = 1, BLUE = 2;
int[] channelNum = {-1, -1, -1};
// We examine the band names looking for "red...", "green...", "blue...".
// Note that the channel numbers we record are indexed from 1, not 0.
for (int i = 0; i < numBands; i++) {
String name = sampleDimensionNames[i].toLowerCase();
if (name != null) {
if (name.matches("red.*")) {
channelNum[RED] = i + 1;
} else if (name.matches("green.*")) {
channelNum[GREEN] = i + 1;
} else if (name.matches("blue.*")) {
channelNum[BLUE] = i + 1;
}
}
}
// If we didn't find named bands "red...", "green...", "blue..."
// we fall back to using the first three bands in order
if (channelNum[RED] < 0 || channelNum[GREEN] < 0 || channelNum[BLUE] < 0) {
channelNum[RED] = 1;
channelNum[GREEN] = 2;
channelNum[BLUE] = 3;
}
// Now we create a RasterSymbolizer using the selected channels
SelectedChannelType[] sct = new SelectedChannelType[cov.getNumSampleDimensions()];
ContrastEnhancement ce = sf.contrastEnhancement(ff.literal(1.0), ContrastMethod.NORMALIZE);
for (int i = 0; i < 3; i++) {
sct[i] = sf.createSelectedChannelType(String.valueOf(channelNum[i]), ce);
}
RasterSymbolizer sym = sf.getDefaultRasterSymbolizer();
ChannelSelection sel = sf.channelSelection(sct[RED], sct[GREEN], sct[BLUE]);
sym.setChannelSelection(sel);
return SLD.wrapSymbolizers(sym);
}
}
// docs end source