/*
* GeoTools - OpenSource mapping toolkit
* http://geotools.org
* (C) 2007, GeoTools Project Managment Committee (PMC)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
package org.geotools.renderedimage.viewer;
import java.awt.BorderLayout;
import java.awt.RenderingHints;
import java.awt.Transparency;
import java.awt.image.DataBuffer;
import java.awt.image.IndexColorModel;
import java.awt.image.RenderedImage;
import java.awt.image.SampleModel;
import java.awt.image.renderable.ParameterBlock;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import javax.media.jai.JAI;
import javax.media.jai.ParameterBlockJAI;
import javax.media.jai.PlanarImage;
import javax.media.jai.ROI;
import javax.media.jai.RenderedOp;
import javax.swing.JComponent;
import javax.swing.JEditorPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
/**
* Tabbed {@link RenderedImage} information display
*
* @author Andrea Aime
* @author Daniele Romagnoli, GeoSolutions SAS
* @author Simone Giannecchini, GeoSolutions SAS
*
*
* @source $URL: http://svn.osgeo.org/geotools/trunk/modules/library/render/src/main/java/org/geotools/renderedimage/viewer/RenderedImageInfoPanel.java $
*/
public class RenderedImageInfoPanel extends JPanel {
// Data buffer type to name map
private static final Map<Integer, String> TYPE_MAP = new HashMap<Integer, String>();
// Rendering key to name map
private static final Map<Object, String> KEY_MAP = new HashMap<Object, String>();
JTabbedPane tabs;
JEditorPane generalPanel;
JEditorPane propertiesPanel;
private JEditorPane operationPanel;
private ImageViewer viewer;
private ImageViewer roiViewer;
private boolean showHistogram = true;
private DisplayHistogram histogramPanel= new DisplayHistogram("");
private boolean showRoi = false;
static {
TYPE_MAP.put(DataBuffer.TYPE_BYTE, "Byte");
TYPE_MAP.put(DataBuffer.TYPE_DOUBLE, "Double");
TYPE_MAP.put(DataBuffer.TYPE_FLOAT, "Float");
TYPE_MAP.put(DataBuffer.TYPE_INT, "Int");
TYPE_MAP.put(DataBuffer.TYPE_SHORT, "Short");
TYPE_MAP.put(DataBuffer.TYPE_UNDEFINED, "Undefined");
TYPE_MAP.put(DataBuffer.TYPE_USHORT, "Short");
try {
Field[] fields = JAI.class.getFields();
for (Field field : fields) {
final int modifiers = field.getModifiers();
// funny enough most KEY in JAI are not final...
if (Modifier.isStatic(modifiers)
&& Modifier.isPublic(modifiers)
&& field.getName().startsWith("KEY_")) {
KEY_MAP.put(field.get(null), field.getName());
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
public RenderedImageInfoPanel() {
this(false, false);
}
public RenderedImageInfoPanel(final boolean showHistogram){
this(showHistogram,false);
}
public RenderedImageInfoPanel(final boolean showHistogram, final boolean showRoi) {
setLayout(new BorderLayout());
tabs = new JTabbedPane();
add(tabs, BorderLayout.CENTER);
this.showHistogram = showHistogram;
this.showRoi = showRoi;
generalPanel = buildHtmlPane();
propertiesPanel = buildHtmlPane();
operationPanel = buildHtmlPane();
if (showRoi){
roiViewer = new ImageViewer();
viewer = new ImageViewer(roiViewer);
roiViewer.setRelatedViewer(viewer);
} else {
viewer = new ImageViewer();
}
tabs.addTab("General information", scroll(generalPanel));
tabs.addTab("Viewer", viewer);
tabs.addTab("Properties", scroll(propertiesPanel));
tabs.addTab("Operation", scroll(operationPanel));
if (showHistogram)
tabs.addTab("Histogram", scroll(histogramPanel));
if (showRoi)
tabs.addTab("ROIViewer", roiViewer);
}
private JScrollPane scroll(JComponent pane) {
JScrollPane scroll = new JScrollPane(pane);
return scroll;
}
private JEditorPane buildHtmlPane() {
JEditorPane pane = new ScrollTopEditorPane("text/html", "");
pane.setEditable(false);
return pane;
}
public void setImage(RenderedImage image) {
buildGeneralInfoPane(image);
buildPropertiesPane(image);
if (image instanceof RenderedOp) {
operationPanel.setEnabled(true);
buildOpPane((RenderedOp) image);
} else {
operationPanel.setEnabled(false);
}
if (showHistogram)
histogramPanel.setImage(PlanarImage.wrapRenderedImage(image));
viewer.setImage(image);
if (showRoi){
if (image instanceof RenderedOp){
final Object object = image.getProperty("ROI");
if (object != null && object instanceof ROI){
ROI roi = (ROI) object;
roiViewer.setImage(roi.getAsImage());
}
}
}
}
void buildOpPane(RenderedOp image) {
final HTMLBuilder hb = new HTMLBuilder();
hb.title("Operation");
hb.dataLine("Name", image.getOperationName());
hb.title("Parameters");
final ParameterBlock block = image.getParameterBlock();
Vector<Object> paramValues = block.getParameters();
for (int i = 0; i < paramValues.size(); i++) {
String name = "Parameter " + (i + 1);
if (block instanceof ParameterBlockJAI) {
name = ((ParameterBlockJAI) block).getParameterListDescriptor()
.getParamNames()[i];
}
hb.dataLine(name, paramValues.get(i));
}
hb.title("Hints");
RenderingHints hints = image.getRenderingHints();
List keys = new ArrayList(hints.keySet());
for (Object key : keys) {
String label = KEY_MAP.get(key);
if (label == null)
label = key.toString();
hb.dataLine(label, hints.get(key));
}
operationPanel.setText(hb.getHtml());
}
void buildPropertiesPane(RenderedImage source) {
HTMLBuilder hb = new HTMLBuilder();
hb.title("Properties");
String[] properties = source.getPropertyNames();
if(properties==null)
return;
Arrays.sort(properties);
for (String propName : properties) {
hb.dataLine(propName, source.getProperty(propName));
}
propertiesPanel.setText(hb.getHtml());
operationPanel.setCaretPosition(0);
}
void buildGeneralInfoPane(RenderedImage image) {
HTMLBuilder hb = new HTMLBuilder();
hb.title("Abstract");
hb.dataLine("Name", getImageName(image));
hb.dataLine("Image class", image.getClass());
hb.dataLine("Image size", image.getWidth() + " x " + image.getHeight());
hb.title("Tiles organisation");
int tw = image.getTileWidth();
int th = image.getTileHeight();
int ytc = image.getNumYTiles();
int xtc = image.getNumXTiles();
hb.dataLine("Tile size", tw + " x " + th);
hb.dataLine("Tile grid", xtc + " x " + ytc + //
" (" + tw * xtc + " x " + th * ytc + ")");
hb.dataLine("Tile offsets x,y", image.getTileGridXOffset() + ", "
+ image.getTileGridYOffset());
hb.dataLine("Min tile x,y", image.getMinTileX() + ", "
+ image.getMinTileY());
hb.title("Sample model");
SampleModel sm = image.getSampleModel();
hb.dataLine("Sample model", sm.getClass());
hb.dataLine("Size", sm.getWidth() + " x " + sm.getHeight());
hb.dataLine("Bands", sm.getNumBands());
hb.dataLine("Bands", TYPE_MAP.get(sm.getDataType()));
hb.title("Color model");
hb.dataLine("Color model", image.getColorModel().getClass());
switch(image.getColorModel().getTransparency()){
case Transparency.OPAQUE:
hb.dataLine("Transparency", "Opaque");
break;
case Transparency.TRANSLUCENT:
hb.dataLine("Transparency", "Translucent");
break;
case Transparency.BITMASK:
hb.dataLine("Transparency", "Bitmask");
break;
}
if(image.getColorModel() instanceof IndexColorModel)
{
final IndexColorModel icm = (IndexColorModel) image.getColorModel();
//transparent pixel
hb.dataLine("Transparent Pixel",Integer.toString(icm.getTransparentPixel()));
// lut
hb.dataLine("ColorMap Size",Integer.toString(icm.getMapSize()));
final int numbands=icm.hasAlpha()?4:3;
final byte[][] cmap= new byte[numbands][icm.getMapSize()];
icm.getReds(cmap[0]);
icm.getGreens(cmap[1]);
icm.getBlues(cmap[2]);
if(numbands==4)
icm.getAlphas(cmap[3]);
final StringBuilder b= new StringBuilder();
for(int i=0;i<icm.getMapSize();i++){
b.append("(").append(i).append(")-").append("[").append(cmap[0][i]).append(",").append(cmap[1][i]).append(",").append(cmap[2][i]);
if(numbands==4)
b.append(",").append(cmap[3][i]);
b.append("]").append("\n");
}
hb.dataLine("ColorMap",b.toString());
}
hb.dataLine("Color space", image.getColorModel().getColorSpace().getClass());
hb.title("Sources");
List<RenderedImage> sources = image.getSources();
if(sources==null)
return;
final int size= sources.size();
for (int i = 0; i < size; i++) {
hb.dataLine("Source " + (i + 1), getImageName(sources.get(i)));
}
generalPanel.setText(hb.getHtml());
}
private String getImageName(RenderedImage source) {
if (source instanceof RenderedOp) {
return "RenderedOp, <i>" + ((RenderedOp) source).getOperationName()
+ "</i>";
} else {
return "Generic <i>" + source.getClass() + "</i>";
}
}
/**
* Simple variation over JEditorPane making the caret be at top each time
* the text is set into the pane
*
* @author Andrea Aime
*
*/
private static class ScrollTopEditorPane extends JEditorPane {
public ScrollTopEditorPane(String type, String text) {
super(type, text);
}
@Override
public void setText(String t) {
super.setText(t);
setCaretPosition(0);
}
}
}