/* * Created on 03.01.2006 for PIROL * * SVN header information: * $Author: LBST-PF-3\orahn $ * $Rev: 2509 $ * $Date: 2006-10-06 12:01:50 +0200 (Fr, 06 Okt 2006) $ * $Id: RasterImageLayer.java 2509 2006-10-06 10:01:50Z LBST-PF-3\orahn $ */ package org.openjump.core.rasterimage; import java.awt.Color; import java.awt.Graphics2D; import java.awt.Image; import java.awt.Point; import java.awt.Rectangle; import java.awt.geom.NoninvertibleTransformException; import java.awt.geom.Point2D; import java.awt.image.BufferedImage; import java.awt.image.ColorModel; import java.awt.image.DataBuffer; import java.awt.image.Raster; import java.awt.image.RenderedImage; import java.awt.image.WritableRaster; import java.awt.image.renderable.ParameterBlock; import java.io.File; import java.io.IOException; import javax.imageio.ImageIO; import javax.media.jai.JAI; import javax.media.jai.PlanarImage; import javax.media.jai.RenderedOp; import org.openjump.util.metaData.MetaDataMap; import org.openjump.util.metaData.ObjectContainingMetaInformation; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Envelope; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.GeometryFactory; import com.vividsolutions.jts.geom.Polygon; import com.vividsolutions.jump.I18N; import com.vividsolutions.jump.util.Blackboard; import com.vividsolutions.jump.workbench.WorkbenchContext; import com.vividsolutions.jump.workbench.model.AbstractLayerable; import com.vividsolutions.jump.workbench.model.LayerManager; import com.vividsolutions.jump.workbench.plugin.PlugInContext; import com.vividsolutions.jump.workbench.ui.LayerNameRenderer; import com.vividsolutions.jump.workbench.ui.LayerViewPanel; import com.vividsolutions.jump.workbench.ui.Viewport; /** * Layer representing a georeferenced raster image (e.g. an areal photography) in OpenJump. * * @author Ole Rahn * <br> * <br>FH Osnabrück - University of Applied Sciences Osnabrück, * <br>Project: PIROL (2006), * <br>Subproject: Daten- und Wissensmanagement * * @version $Rev: 2509 $ * modified: [sstein]: 16.Feb.2009 changed logger-entries to comments, used frame.warnUser */ public class RasterImageLayer extends AbstractLayerable implements ObjectContainingMetaInformation { protected static Blackboard blackboard = null; protected final static String BLACKBOARD_KEY_PLUGINCONTEXT = PlugInContext.class.getName(); protected final static String BLACKBOARD_KEY_WORKBENCHCONTEXT = PlugInContext.class.getName(); protected int lastImgProcessingMode = 0; protected final static int MODE_NONE = 0; protected final static int MODE_SCALINGFIRST = 1; protected final static int MODE_CLIPPINGFIRST = 2; protected final static int MODE_FASTDISPLAY = 3; protected Rectangle imagePart, oldImagePart, visibleRect = null; protected double scaleXImg2Canvas, oldScaleXImg2Canvas, scaleYImg2Canvas; protected int xOffset, yOffset; //protected static PersonalLogger logger = new PersonalLogger(DebugUserIds.OLE); protected double transparencyLevel = .0f; protected static long availRAM = Runtime.getRuntime().maxMemory(); protected static double freeRamFactor = 0.5; protected static double minRamToKeepFree = availRAM * freeRamFactor; //[sstein 9.Aug.2010] // The value below is set dynamically based on available memory // now its 200x200px as min (originally it was 500x500) //protected static int maxPixelsForFastDisplayMode = 40000; protected static int maxPixelsForFastDisplayMode = 250000; protected String imageFileName = null; protected int origImageWidth, origImageHeight; protected boolean imageSet = false; protected PlanarImage image = null; //-- [sstein 2nd Aug 2010] new, since we scale the image now for display protected static Raster rasterData = null; protected boolean rasterDataChanged = false; //may be needed for rescaling the image values protected boolean wasScaledForDisplay = false; //-- end protected PlanarImage imageProcessingStep1 = null, imageProcessingStep2 = null; protected Envelope envelope = null, visibleEnv = null; /** * Flag to decide, if events are fired automatically, if the appearance (envelope, etc.) changes.<br> * default: true */ protected boolean firingAppearanceEvents = true; /** * Flag to control if the image should be deleted from RAM as soon as possible to save RAM or if it should be keeped e.g. because it was generated * dynamically and can not be loaded from a file again, once it was deleted. */ protected boolean needToKeepImage = false; protected static final Point nullpunkt = new Point(0,0); protected Color transparentColor = null; protected boolean transparencyColorNeedsToBeApplied = false; /** * for java2xml */ public RasterImageLayer() { super(); getBlackboard().put(LayerNameRenderer.USE_CLOCK_ANIMATION_KEY, true); } /** *@param name name of the layer *@param layerManager *@param imageToDisplay the image (if already loaded) or null *@param newRaster the raster (if already loaded) or null *@param envelope real-world coordinates of the image */ public RasterImageLayer(String name, LayerManager layerManager, String imageFileName, RenderedImage imageToDisplay, Raster newRaster, Envelope envelope) { super(name, layerManager); getBlackboard().put(LayerNameRenderer.USE_CLOCK_ANIMATION_KEY, true); this.imageFileName = imageFileName; this.envelope = envelope; if (imageToDisplay != null) this.setImage(javax.media.jai.PlanarImage.wrapRenderedImage(imageToDisplay)); if (newRaster != null) this.setRasterData(newRaster); //[sstein 9.Aug.2010] long avram = getAvailRAM(); if(avram > 256000000){ maxPixelsForFastDisplayMode = 250000; //500x500 px } if(avram > 750000000){ maxPixelsForFastDisplayMode = 4000000; //2000x2000 px } //[sstein end] } /** * Constructor to be used in case the image was not loaded from a file, so there is * no file name, but an image * *@param name name of the layer *@param layerManager *@param imageToDisplay the image (if already loaded) or null *@param newRaster the raster (if already loaded) or null *@param envelope real-world coordinates of the image */ public RasterImageLayer(String name, LayerManager layerManager, RenderedImage imageToDisplay, Raster newRaster, Envelope envelope) { super(name, layerManager); getBlackboard().put(LayerNameRenderer.USE_CLOCK_ANIMATION_KEY, true); this.setNeedToKeepImage(true); this.envelope = envelope; if (imageToDisplay != null) this.setImage(javax.media.jai.PlanarImage.wrapRenderedImage(imageToDisplay)); else{ //logger.printError("given image is NULL"); } if (newRaster != null) this.setRasterData(newRaster); else{ //logger.printError("given raster is NULL"); } //[sstein 9.Aug.2010] long avram = getAvailRAM(); if(avram > 256000000){ maxPixelsForFastDisplayMode = 250000; //500x500 px } if(avram > 750000000){ maxPixelsForFastDisplayMode = 563500; //750x750 px } //[sstein end] } /** *@inheritDoc */ public Blackboard getBlackboard() { if (RasterImageLayer.blackboard == null) RasterImageLayer.blackboard = new Blackboard(); return RasterImageLayer.blackboard; } public Object clone() throws CloneNotSupportedException { if (this.isNeedToKeepImage()) return new RasterImageLayer(this.getName(), this.getLayerManager(), this.getImageForDisplay(), this.getRasterData(), new Envelope(this.getEnvelope())); return new RasterImageLayer(this.getName(), this.getLayerManager(), this.getImageFileName(), this.getImageForDisplay(), this.getRasterData(), new Envelope(this.getEnvelope())); } /** * apply a scale operation to the image and return the * new image. */ protected PlanarImage scaleImage(PlanarImage im, float xScale, float yScale) { ParameterBlock pb = new ParameterBlock(); pb.addSource(im); pb.add(xScale); pb.add(yScale); return JAI.create("Scale", pb, null); } protected PlanarImage createOneColorImage(){ //logger.printDebug("fixing 1px scale: scaleXImg2Canvas = " + scaleXImg2Canvas + ", scaleYImg2Canvas = " + scaleYImg2Canvas); //logger.printDebug("this.imageProcessingStep1: " + this.imageProcessingStep1 .getWidth() + ", " + this.imageProcessingStep1.getHeight()); scaleXImg2Canvas = Math.min( Math.abs(scaleXImg2Canvas), Math.abs(visibleRect.width) ); scaleYImg2Canvas = Math.min( Math.abs(scaleYImg2Canvas), Math.abs(visibleRect.height) ); //logger.printDebug("fixed 1px scale: scaleXImg2Canvas = " + scaleXImg2Canvas + ", scaleYImg2Canvas = " + scaleYImg2Canvas); BufferedImage bim = new BufferedImage(visibleRect.width, visibleRect.height, BufferedImage.TYPE_INT_ARGB); Graphics2D grfcs = bim.createGraphics(); grfcs.setColor(new Color(this.imageProcessingStep1.getAsBufferedImage().getRGB(0,0))); //logger.printDebug("color: " + new Color(this.imageProcessingStep1.getAsBufferedImage().getRGB(0,0)).toString()); grfcs.fillRect( 0, 0, bim.getWidth(), bim.getHeight() ); grfcs.dispose(); return PlanarImage.wrapRenderedImage(bim); } /** * Creates the image to draw */ public BufferedImage createImage(LayerViewPanel layerViewPanel) { Viewport viewport = layerViewPanel.getViewport(); if (!this.isVisible() || this.transparencyLevel >= 1.0){ this.setImageProcessingMode(RasterImageLayer.MODE_NONE); this.clearImageAndRaster(true); //logger.printDebug("!visible"); return null; } BufferedImage imageToDraw = null; try { Point2D upperLeftCornerOfImage = null; Point2D lowerRightCornerOfImage = null; try { upperLeftCornerOfImage = viewport.toViewPoint(new Coordinate(this.getEnvelope().getMinX(), this.getEnvelope().getMaxY())); lowerRightCornerOfImage = viewport.toViewPoint(new Coordinate(this.getEnvelope().getMaxX(), this.getEnvelope().getMinY())); } catch(java.awt.geom.NoninvertibleTransformException ne) { //logger.printError(ne.getLocalizedMessage()); ne.printStackTrace(); return null; } visibleRect = viewport.getPanel().getVisibleRect(); int visibleX1 = visibleRect.x; int visibleY1 = visibleRect.y; int visibleX2 = visibleX1 + visibleRect.width; int visibleY2 = visibleY1 + visibleRect.height; Coordinate upperLeftVisible = viewport.toModelCoordinate(nullpunkt); Coordinate lowerRightVisible = viewport.toModelCoordinate(new Point(visibleX2, visibleY2)); Envelope newVisibleEnv = new Envelope(upperLeftVisible.x, lowerRightVisible.x, upperLeftVisible.y, lowerRightVisible.y); double scaledWidth = lowerRightCornerOfImage.getX() - upperLeftCornerOfImage.getX(); double scaledHeight = upperLeftCornerOfImage.getY() - lowerRightCornerOfImage.getY(); if (!this.isImageSet()){ this.reLoadImage(); } scaleXImg2Canvas = scaledWidth / this.origImageWidth; scaleYImg2Canvas = scaledHeight / this.origImageHeight; if (this.visibleEnv == null || this.visibleEnv.getMinX() != newVisibleEnv.getMinX() || this.visibleEnv.getMaxX() != newVisibleEnv.getMaxX() || this.visibleEnv.getMinY() != newVisibleEnv.getMinY() || this.visibleEnv.getMaxY() != newVisibleEnv.getMaxY() ){ this.visibleEnv = newVisibleEnv; if ( (this.origImageWidth * this.origImageHeight) < RasterImageLayer.getMaxPixelsForFastDisplayMode() ){ //int pixels = this.origImageWidth * this.origImageHeight; //int maxpixels = RasterImageLayer.getMaxPixelsForFastDisplayMode(); //-- faster display (uses more RAM) for small images this.setImageProcessingMode(RasterImageLayer.MODE_FASTDISPLAY); if (this.isImageNull()){ this.reLoadImage(); } //[sstein 9.Aug.2010] //problem: putting the stuff below here will also avoid the first re-scaling of the image // for better display, so I added the additional scaling stuff long totalMem = Runtime.getRuntime().totalMemory(); long freeMem = Runtime.getRuntime().freeMemory(); long committedMemory = totalMem - freeMem; double maxMemoryToCommit = availRAM - minRamToKeepFree; boolean needFreeRAM = (committedMemory > maxMemoryToCommit); if(needFreeRAM == false){ if (wasScaledForDisplay == false){ setImage(stretchImageValuesForDisplay(getImageForDisplay())); wasScaledForDisplay = true; } this.setNeedToKeepImage(true); //so small images are not reloaded every time } //[sstein end] this.imagePart = this.getVisibleImageCoordinatesOfImage( this.origImageWidth, this.origImageHeight, this.visibleEnv, this.getEnvelope() ); if (this.imageProcessingStep2 == null || (scaleXImg2Canvas != this.oldScaleXImg2Canvas || !RasterImageLayer.tilesAreNotNullAndCongruent( this.imagePart, this.oldImagePart))){ this.imageProcessingStep1 = this.getVisiblePartOfTheImage( this.getImageForDisplay(), this.imagePart ); if ( this.imageProcessingStep1 != null) { // avoid an 1 pixel by 1 pixel image to get scaled to thousands by thousands pixels causing an out of memory error if (this.imagePart.width == 1 || this.imagePart.height == 1){ this.xOffset = 0; this.yOffset = 0; this.imageProcessingStep2 = this.createOneColorImage(); } else { this.imageProcessingStep2 = this.getScaledImageMatchingVisible( this.imageProcessingStep1, scaleXImg2Canvas, scaleYImg2Canvas ); } } else { return null; } if (this.transparentColor!=null) transparencyColorNeedsToBeApplied = true; this.imageProcessingStep1 = null; this.xOffset = (int)(this.xOffset *scaleXImg2Canvas); this.yOffset = (int)(this.yOffset *(-scaleYImg2Canvas)); this.oldScaleXImg2Canvas = this.scaleXImg2Canvas; this.oldImagePart = this.imagePart; } } else if ( (scaleXImg2Canvas >= 1) || (scaledWidth > 2500 && visibleRect.width < 1500)){ this.setImageProcessingMode(RasterImageLayer.MODE_CLIPPINGFIRST); this.imagePart = this.getVisibleImageCoordinatesOfImage( this.origImageWidth, this.origImageHeight, visibleEnv, this.getEnvelope() ); if (this.imageProcessingStep2 == null || (scaleXImg2Canvas != this.oldScaleXImg2Canvas || !RasterImageLayer.tilesAreNotNullAndCongruent( this.imagePart, this.oldImagePart))){ if (!RasterImageLayer.tilesAreNotNullAndCongruent(this.oldImagePart, this.imagePart)){ this.imageProcessingStep1 = null; if (this.isImageNull()){ this.reLoadImage(); } this.imageProcessingStep1 = this.getVisiblePartOfTheImage( this.getImageForDisplay(), this.imagePart ); this.clearImageAndRaster(false); } if ( this.imageProcessingStep1 != null) { // avoid an 1 pixel by 1 pixel image to get scaled to thousands by thousands pixels causing an out of memory error if (this.imagePart.width == 1 || this.imagePart.height == 1){ this.xOffset = 0; this.yOffset = 0; this.imageProcessingStep2 = this.createOneColorImage(); } else { this.imageProcessingStep2 = this.getScaledImageMatchingVisible( this.imageProcessingStep1, scaleXImg2Canvas, scaleYImg2Canvas ); } } else { return null; } if (this.transparentColor!=null) transparencyColorNeedsToBeApplied = true; this.imageProcessingStep1 = null; this.xOffset = (int)(this.xOffset *scaleXImg2Canvas); this.yOffset = (int)(this.yOffset *(-scaleYImg2Canvas)); this.oldScaleXImg2Canvas = this.scaleXImg2Canvas; this.oldImagePart = this.imagePart; } } else { this.setImageProcessingMode(RasterImageLayer.MODE_SCALINGFIRST); if ( scaleXImg2Canvas != this.oldScaleXImg2Canvas || this.imageProcessingStep1 == null){ this.imageProcessingStep1 = null; if (this.isImageNull()){ this.reLoadImage(); } this.imageProcessingStep1 = this.getScaledImageMatchingVisible( this.getImageForDisplay(), scaleXImg2Canvas, scaleYImg2Canvas ); this.clearImageAndRaster(false); this.oldScaleXImg2Canvas = this.scaleXImg2Canvas; } if ( this.imageProcessingStep1 != null ){ this.imagePart = this.getVisibleImageCoordinatesOfImage( this.imageProcessingStep1, visibleEnv, this.getEnvelope() ); if ( this.imageProcessingStep2 == null || !RasterImageLayer.tilesAreNotNullAndCongruent( this.imagePart, this.oldImagePart)){ this.imageProcessingStep2 = this.getVisiblePartOfTheImage( PlanarImage.wrapRenderedImage(this.imageProcessingStep1), this.imagePart ); this.oldImagePart = this.imagePart; } } else { return null; } if (this.transparentColor!=null) transparencyColorNeedsToBeApplied = true; } } if (this.imageProcessingStep2 != null && transparencyColorNeedsToBeApplied ){ imageToDraw = this.setupTransparency(this.imageProcessingStep2); } else if (this.imageProcessingStep2 != null) { imageToDraw = this.imageProcessingStep2.getAsBufferedImage(); } } catch (Exception e){ //logger.printError(e.getMessage()); e.printStackTrace(); } if (Runtime.getRuntime().freeMemory() < RasterImageLayer.getMinRamToKeepFree()){ this.clearImageAndRaster(true); } if (imageToDraw != null) { return imageToDraw; } else if (this.imageProcessingStep2!=null) { return this.imageProcessingStep2.getAsBufferedImage(); } return null; } /** * deletes image from RAM (if it is not to be kept and if the RAM consumption is high) * and calls the garbage collector, if the <code>garbageCollect</code> is true. *@param garbageCollect if true the garbage collector will be called (this parameter may be overridden, if there is not enough RAM available...) */ public boolean clearImageAndRaster(boolean garbageCollect){ //TODO: [sstein 9.Aug.2010] not sure if below condition is correct, since it // does not account for Xmx (max memory), only for the actual memory // Hence we should work with committed memory as I did above??? boolean reallyNeedToFreeRAM = (Runtime.getRuntime().freeMemory() < minRamToKeepFree); if (!this.needToKeepImage && reallyNeedToFreeRAM ){ this.image = null; rasterData = null; //[sstein 2Aug2010] line added this.wasScaledForDisplay = false; //[sstein 20Aug2010] line added } if (garbageCollect){ Runtime.getRuntime().gc(); } return reallyNeedToFreeRAM; } /** * flushes all images from the RAM. *@param garbageCollect if true the garbage collector will be called (this parameter may be overridden, if there is not enough RAM available...) */ public void flushImages(boolean garbageCollect){ if (this.image!=null) this.image.dispose(); this.image = null; if (this.imageProcessingStep1!=null) this.imageProcessingStep1.dispose(); this.imageProcessingStep1 = null; if (this.imageProcessingStep2!=null) this.imageProcessingStep2.dispose(); this.imageProcessingStep2 = null; if (garbageCollect){ Runtime.getRuntime().gc(); } } public void reLoadImage(){ WorkbenchContext context = this.getWorkbenchContext(); if (this.image == null && !this.needToKeepImage){ this.setImage( RasterImageLayer.loadImage( context, imageFileName ) ); } else if (this.image == null && this.needToKeepImage){ //logger.printError("was advised to keep image, but there is none!"); } } /** * use this to assign the raster data again * the method is called from getRasterData(); */ public void reLoadImageButKeepImageForDisplay(){ WorkbenchContext context = this.getWorkbenchContext(); PlanarImage pi = this.getImageForDisplay(); //[sstein 24.Sept.2010] commented out: //PlanarImage dontNeedThisImage = RasterImageLayer.loadImage( context, imageFileName); //causes error for .clone() this.setImage(pi); } /** * Returns the dimensions (width and height in px) of the image as a <code>Point</code> object. * The clue is that only the image file's header is read to get this information, so it's quite * fast, because the image was not entirely read. *@param context the WorkbenchContext *@param filenameOrURL the image file's name or URL *@return a point which's x is the image's width and y is the height */ public static Point getImageDimensions(WorkbenchContext context, String filenameOrURL) { if (!filenameOrURL.toLowerCase().endsWith(".jpg") && !filenameOrURL.toLowerCase().endsWith(".flt") && !filenameOrURL.toLowerCase().endsWith(".asc")){ try { // JAI required!! javax.media.jai.PlanarImage pImage = javax.media.jai.JAI.create("fileload", filenameOrURL); if (pImage != null) { return new Point(pImage.getWidth(), pImage.getHeight()); } } catch (Throwable e) { //logger.printError(e.getLocalizedMessage()); if (e.getMessage().indexOf("Planar (band-sequential) format TIFF is not supported") > -1) { context.getWorkbench().getFrame().warnUser("unsupported-tiff"); } else { context.getWorkbench().getFrame().warnUser("problems-loading-image"+ e.getMessage()); } } }else if(filenameOrURL.toLowerCase().endsWith(".flt")){ try{ GridFloat gf = new GridFloat(filenameOrURL); return new Point(gf.getnCols(), gf.getnRows()); }catch(Throwable e){ //logger.printError(e.getLocalizedMessage()); if (e.getMessage().indexOf("Error in FLT file") > -1) { context.getWorkbench().getFrame().warnUser("unsupported-flt"); } else { context.getWorkbench().getFrame().warnUser("problems-loading-image"+ e.getMessage()); } } }else if(filenameOrURL.toLowerCase().endsWith(".asc")){ try{ GridAscii ga = new GridAscii(filenameOrURL); return new Point(ga.getnCols(), ga.getnRows()); }catch(Throwable e){ //logger.printError(e.getLocalizedMessage()); if (e.getMessage().indexOf("Error in Grid Ascii file") > -1) { context.getWorkbench().getFrame().warnUser("unsupported-asc"); } else { context.getWorkbench().getFrame().warnUser("problems-loading-image"+ e.getMessage()); } } } else { BufferedImage image = null; try { image = ImageIO.read(new File(filenameOrURL)); } catch (IOException e) { e.printStackTrace(); } return new Point(image.getWidth(), image.getHeight()); } return null; } public final static PlanarImage loadImage(WorkbenchContext context, String filenameOrURL) { if (filenameOrURL.toLowerCase().endsWith(".gif") || filenameOrURL.toLowerCase().endsWith(".png") || filenameOrURL.toLowerCase().endsWith(".tif") || filenameOrURL.toLowerCase().endsWith(".tiff")) { try { javax.media.jai.PlanarImage pImage = javax.media.jai.JAI.create("fileload", filenameOrURL); //-- [sstein 2 Aug 2010] // dealing now with an Image that will be modified for better display Raster rData = pImage.copyData(); //copy data so we do not get a ref rasterData = rData; PlanarImage surrogatImage = null; surrogatImage = stretchImageValuesForDisplay(pImage); //return pImage; //surrogatImage = pImage; //for testing return surrogatImage; //-- end } catch (Throwable e) { //logger.printError(e.getMessage()); if(context != null){ if (e.getMessage().indexOf("Planar (band-sequential) format TIFF is not supported") > -1) { context.getWorkbench().getFrame().warnUser(I18N.get("unsupported-tiff")); } else { context.getWorkbench().getFrame().warnUser(I18N.get("problems-loading-image")+ e.getMessage()); } } e.printStackTrace(); return null; } } else if (filenameOrURL.toLowerCase().endsWith(".jpg")){ PlanarImage pimage = null; try { BufferedImage image = ImageIO.read(new File(filenameOrURL)); //-- [sstein 2 Aug 2010] // dealing now with an Image that will be modified for better dislay pimage = PlanarImage.wrapRenderedImage(image); Raster rData = pimage.copyData(); //copy data so we do not get a ref rasterData = rData; //-- end } catch (IOException e) { e.printStackTrace(); } //-- [sstein 2 Aug 2010] PlanarImage surrogatImage = stretchImageValuesForDisplay(pimage); //return pimage; return surrogatImage; //-- end } else if (filenameOrURL.toLowerCase().endsWith(".flt")){ try{ GridFloat gf = new GridFloat(filenameOrURL); gf.readGrid(); javax.media.jai.PlanarImage pImage = gf.getPlanarImage(); //-- [sstein 3 Aug 2010] // dealing now with an Image that will be modified for better dislay Raster rData = pImage.copyData(); //copy data so we do not get a ref rasterData = rData; //-- sstein end // This rescales values // See http://www.lac.inpe.br/JIPCookbook/2200-display-surrogate.jsp ParameterBlock pbMaxMin = new ParameterBlock(); pbMaxMin.addSource(pImage); RenderedOp extrema = JAI.create("extrema", pbMaxMin); double minValue = gf.getMinVal(); double maxValue = gf.getMaxVal(); double[] subtractThis = new double[1]; subtractThis[0] = minValue; double[] multiplyBy = new double[1]; multiplyBy[0] = 255./(maxValue-minValue); ParameterBlock pbSub = new ParameterBlock(); pbSub.addSource(pImage); pbSub.add(subtractThis); PlanarImage surrogateImage = (PlanarImage)JAI.create("subtractconst",pbSub,null); ParameterBlock pbMult = new ParameterBlock(); pbMult.addSource(surrogateImage); pbMult.add(multiplyBy); surrogateImage = (PlanarImage)JAI.create("multiplyconst",pbMult,null); ParameterBlock pbConvert = new ParameterBlock(); pbConvert.addSource(surrogateImage); pbConvert.add(DataBuffer.TYPE_BYTE); surrogateImage = JAI.create("format", pbConvert); return(surrogateImage); }catch(Throwable e){ //logger.printError(e.getLocalizedMessage()); if (e.getMessage().indexOf("Error in FLT file") > -1) { context.getWorkbench().getFrame().warnUser("unsupported-flt"); } else { context.getWorkbench().getFrame().warnUser("problems-loading-image"+ e.getMessage()); } } } else if (filenameOrURL.toLowerCase().endsWith(".asc")){ try{ GridAscii ga = new GridAscii(filenameOrURL); ga.readGrid(); javax.media.jai.PlanarImage pImage = ga.getPlanarImage(); //-- [sstein 3 Aug 2010] // dealing now with an Image that will be modified for better dislay Raster rData = pImage.copyData(); //copy data so we do not get a ref rasterData = rData; //-- sstein end // This rescales values // See http://www.lac.inpe.br/JIPCookbook/2200-display-surrogate.jsp ParameterBlock pbMaxMin = new ParameterBlock(); pbMaxMin.addSource(pImage); RenderedOp extrema = JAI.create("extrema", pbMaxMin); double minValue = ga.getMinVal(); double maxValue = ga.getMaxVal(); double[] subtractThis = new double[1]; subtractThis[0] = minValue; double[] multiplyBy = new double[1]; multiplyBy[0] = 255./(maxValue-minValue); ParameterBlock pbSub = new ParameterBlock(); pbSub.addSource(pImage); pbSub.add(subtractThis); PlanarImage surrogateImage = (PlanarImage)JAI.create("subtractconst",pbSub,null); ParameterBlock pbMult = new ParameterBlock(); pbMult.addSource(surrogateImage); pbMult.add(multiplyBy); surrogateImage = (PlanarImage)JAI.create("multiplyconst",pbMult,null); ParameterBlock pbConvert = new ParameterBlock(); pbConvert.addSource(surrogateImage); pbConvert.add(DataBuffer.TYPE_BYTE); surrogateImage = JAI.create("format", pbConvert); return(surrogateImage); }catch(Throwable e){ //logger.printError(e.getLocalizedMessage()); if (e.getMessage().indexOf("Error in ASCII file") > -1) { context.getWorkbench().getFrame().warnUser("unsupported-ascii"); } else { context.getWorkbench().getFrame().warnUser("problems-loading-image"+ e.getMessage()); } } } //logger.printError("unsupported image format"); return null; } private static PlanarImage stretchImageValuesForDisplay(RenderedImage pImage){ //-- This rescales values // See http://www.lac.inpe.br/JIPCookbook/2200-display-surrogate.jsp //int width = pImage.getWidth(); //int height = pImage.getHeight(); // Create an array to receive the pixels values with the appropriate number of bands //double[] pixelValues = new double[pImage.getSampleModel().getNumBands()]; // Which are the max and min of the image? We need to know to create the // surrogate image. Let's use the extrema operator to get them. ParameterBlock pbMaxMin = new ParameterBlock(); pbMaxMin.addSource(pImage); RenderedOp extrema = JAI.create("extrema", pbMaxMin); // Must get the extrema of all bands ! double[] allMins = (double[])extrema.getProperty("minimum"); double[] allMaxs = (double[])extrema.getProperty("maximum"); double minValue = allMins[0]; double maxValue = allMaxs[0]; for(int v=1;v<allMins.length;v++) { if (allMins[v] < minValue) minValue = allMins[v]; if (allMaxs[v] > maxValue) maxValue = allMaxs[v]; } // Rescale the image with the parameters double[] subtractThis = new double[1]; subtractThis[0] = minValue; double[] multiplyBy = new double[1]; multiplyBy[0] = 255./(maxValue-minValue); // Now we can rescale the pixels' values: ParameterBlock pbSub = new ParameterBlock(); pbSub.addSource(pImage); pbSub.add(subtractThis); PlanarImage surrogateImage = (PlanarImage)JAI.create("subtractconst",pbSub,null); ParameterBlock pbMult = new ParameterBlock(); pbMult.addSource(surrogateImage); pbMult.add(multiplyBy); surrogateImage = (PlanarImage)JAI.create("multiplyconst",pbMult,null); // Let's convert the data type for displaying. ParameterBlock pbConvert = new ParameterBlock(); pbConvert.addSource(surrogateImage); pbConvert.add(DataBuffer.TYPE_BYTE); surrogateImage = JAI.create("format", pbConvert); return surrogateImage; } /** * @return Envelope with the real world coordinates of the image */ public Envelope getEnvelope() { return envelope; } /** * Sets the Envelope object containing the real world coordinates (e.g. WGS84) of the image - this needs to be set (if it wasn't given to the constructor)! *@param envelope the Envelope */ public void setEnvelope(Envelope envelope) { this.envelope = envelope; this.forceTotalRepaint(); if (this.isFiringAppearanceEvents()) this.fireAppearanceChanged(); } /** * for java2xml *@return the Envelope as string */ public String getXmlEnvelope(){ return this.envelope.toString(); } /** * for java2xml *@param envStr the Envelope as string */ public void setXmlEnvelope(String envStr){ String coords = envStr.substring(envStr.indexOf("[")+1, envStr.indexOf("]")); String[] coordArray = coords.split(","); String[] xCoords = coordArray[0].split(":"); String[] yCoords = coordArray[1].split(":"); double minX = java.lang.Double.parseDouble(xCoords[0]); double maxX = java.lang.Double.parseDouble(xCoords[1]); double minY = java.lang.Double.parseDouble(yCoords[0]); double maxY = java.lang.Double.parseDouble(yCoords[1]); this.setEnvelope( new Envelope( minX, maxX, minY, maxY ) ); } /** * Method to change the coordinates of the image and later apply the * changes to the RasterImageLayer by using {@link RasterImageLayer#setGeometryAsEnvelope(Geometry)}. *@return return the envelope (= bounding box) as a geometry, */ public Polygon getEnvelopeAsGeometry(){ Coordinate[] coordinates = new Coordinate[5]; coordinates[0] = new Coordinate(this.envelope.getMinX(), this.envelope.getMaxY()); coordinates[1] = new Coordinate(this.envelope.getMaxX(), this.envelope.getMaxY()); coordinates[2] = new Coordinate(this.envelope.getMaxX(), this.envelope.getMinY()); coordinates[3] = new Coordinate(this.envelope.getMinX(), this.envelope.getMinY()); coordinates[4] = new Coordinate(this.envelope.getMinX(), this.envelope.getMaxY()); GeometryFactory gf = new GeometryFactory(); return gf.createPolygon(gf.createLinearRing(coordinates), null); } /** * Method to set the coordinates of the image, e.g. after changing them after using {@link RasterImageLayer#getEnvelopeAsGeometry()}. */ public void setGeometryAsEnvelope(Geometry geometry){ this.setEnvelope(geometry.getEnvelopeInternal()); } /** * Add transparency to the image (more exactly: to each pixel which a color == this.transparentColor) *@param pImage the image */ private BufferedImage setupTransparency(PlanarImage pImage){ BufferedImage bim = pImage.getAsBufferedImage(); ColorModel cm = bim.getColorModel(); int fullTransparencyAlpha = 255; if (this.getTransparentColor()==null){ return null; } int transparentColor = this.getTransparentColor().getRGB(); int currentColor = -1; int[] argb = new int[4]; if (!cm.hasAlpha()){ bim = RasterImageLayer.makeBufferedImage(bim); cm = bim.getColorModel(); } for( int w=0; w<bim.getWidth(); w++){ for (int h=0; h<bim.getHeight(); h++){ currentColor = bim.getRGB(w,h); if (currentColor==transparentColor){ argb[0] = fullTransparencyAlpha; argb[1] = cm.getRed(currentColor); argb[2] = cm.getGreen(currentColor); argb[3] = cm.getBlue(currentColor); bim.setRGB(w,h,1,1,argb,0,1); } } } return bim; } private void setImageProcessingMode( int nr ){ if (lastImgProcessingMode != nr){ if (this.imageProcessingStep1!=null) this.imageProcessingStep1.dispose(); this.imageProcessingStep1 = null; if (this.imageProcessingStep2!=null) this.imageProcessingStep2.dispose(); this.imageProcessingStep2 = null; this.imagePart = null; this.oldImagePart = null; this.oldScaleXImg2Canvas = -1; if (Runtime.getRuntime().freeMemory() < RasterImageLayer.getMinRamToKeepFree()){ Runtime.getRuntime().gc(); } this.lastImgProcessingMode = nr; } } private static boolean tilesAreNotNullAndCongruent( Rectangle r1, Rectangle r2 ){ boolean result; if (r1 == null || r2 == null) result = false; else result = (r1.x == r2.x && r1.y == r2.y && r1.width == r2.width && r1.height == r2.height); return result; } /** * creates a BufferedImage out of an Image *@param im the Image *@return the BufferedImage */ public static final BufferedImage makeBufferedImage(Image im) { BufferedImage copy = new BufferedImage(im.getWidth(null), im.getHeight(null), BufferedImage.TYPE_INT_ARGB); // create a graphics context Graphics2D g2d = copy.createGraphics(); // copy image g2d.drawImage(im,0,0,null); g2d.dispose(); return copy; } protected PlanarImage getScaledImageMatchingVisible( PlanarImage toBeScaled, double XscaleImg2Canvas, double YscaleImg2Canvas ){ if (toBeScaled==null) return null; int scaledWidth = (int)(toBeScaled.getWidth() * XscaleImg2Canvas); int scaledHeight = (int)(toBeScaled.getHeight() * Math.abs(YscaleImg2Canvas) ); if (scaledWidth<=0 || scaledHeight<=0) return null; return this.scaleImage(toBeScaled, (float)XscaleImg2Canvas, (float)Math.abs(YscaleImg2Canvas) ); } public BufferedImage getTileAsImage( Envelope wantedEnvelope ){ double imgWidth = this.origImageWidth; double imgHeight = this.origImageHeight; Envelope imageEnv = this.getEnvelope(); double minVisibleX = Math.max(wantedEnvelope.getMinX(), imageEnv.getMinX()); double minVisibleY = Math.max(wantedEnvelope.getMinY(), imageEnv.getMinY()); double maxVisibleX = Math.min(wantedEnvelope.getMaxX(), imageEnv.getMaxX()); double maxVisibleY = Math.min(wantedEnvelope.getMaxY(), imageEnv.getMaxY()); double offset2VisibleX = imageEnv.getMinX() - wantedEnvelope.getMinX(); double offset2VisibleY = wantedEnvelope.getMaxY() - imageEnv.getMaxY(); double scaleX = imgWidth / imageEnv.getWidth(); double scaleY = imgHeight / imageEnv.getHeight(); // use local variables! int xOffset, yOffset, width, height; if (offset2VisibleX >= 0){ xOffset = 0; } else { xOffset = (int)(-offset2VisibleX * scaleX); } if (offset2VisibleY >= 0){ yOffset = 0; } else { yOffset = (int)(-offset2VisibleY * scaleY); } width = (int)((maxVisibleX-minVisibleX) * scaleX); height = (int)((maxVisibleY-minVisibleY) * scaleY); if (width < imgWidth && height < imgHeight){ width += 1; height += 1; } if (width <= 0 || height <= 0) return null; int wantedWidth = (int)(wantedEnvelope.getWidth() * scaleX); int wantedHeight = (int)(wantedEnvelope.getHeight() * scaleY); if (this.image==null){ this.reLoadImage(); } BufferedImage imgTile = this.image.getAsBufferedImage( new Rectangle(xOffset, yOffset, width, height), this.image.getColorModel()); BufferedImage result = new BufferedImage( wantedWidth, wantedHeight, BufferedImage.TYPE_INT_ARGB); Graphics2D graf = result.createGraphics(); Color backgroundColor = (this.transparentColor!=null)?this.transparentColor:Color.white; graf.fillRect(0,0,wantedWidth, wantedHeight); int xTileOffset,yTileOffset; if (xOffset > 0){ xTileOffset = 0; } else { xTileOffset = (int)(offset2VisibleX * scaleX); } if (yOffset > 0){ yTileOffset = 0; } else { yTileOffset = (int)(offset2VisibleY * scaleY); } graf.drawImage(imgTile, xTileOffset, yTileOffset, imgTile.getWidth(), imgTile.getHeight(), backgroundColor, null); graf.dispose(); this.clearImageAndRaster(false); return result; } public Raster getTileAsRaster( Envelope wantedEnvelope ){ double imgWidth = this.origImageWidth; double imgHeight = this.origImageHeight; Envelope imageEnv = this.getEnvelope(); double minVisibleX = Math.max(wantedEnvelope.getMinX(), imageEnv.getMinX()); double minVisibleY = Math.max(wantedEnvelope.getMinY(), imageEnv.getMinY()); double maxVisibleX = Math.min(wantedEnvelope.getMaxX(), imageEnv.getMaxX()); double maxVisibleY = Math.min(wantedEnvelope.getMaxY(), imageEnv.getMaxY()); double offset2VisibleX = imageEnv.getMinX() - wantedEnvelope.getMinX(); double offset2VisibleY = wantedEnvelope.getMaxY() - imageEnv.getMaxY(); double scaleX = imgWidth / imageEnv.getWidth(); double scaleY = imgHeight / imageEnv.getHeight(); // use local variables! int xOffset, yOffset, width, height; if (offset2VisibleX >= 0){ xOffset = 0; } else { xOffset = (int)(-offset2VisibleX * scaleX); } if (offset2VisibleY >= 0){ yOffset = 0; } else { yOffset = (int)(-offset2VisibleY * scaleY); } width = (int)((maxVisibleX-minVisibleX) * scaleX); height = (int)((maxVisibleY-minVisibleY) * scaleY); if (width < imgWidth && height < imgHeight){ width += 1; height += 1; } if (width <= 0 || height <= 0) return null; int wantedWidth = (int)(wantedEnvelope.getWidth() * scaleX); int wantedHeight = (int)(wantedEnvelope.getHeight() * scaleY); if (rasterData==null){ this.reLoadImage(); } ColorModel colorModel = PlanarImage.createColorModel(rasterData.getSampleModel()); BufferedImage bufimg = new BufferedImage(colorModel, (WritableRaster) rasterData, false, null); PlanarImage pimage = PlanarImage.wrapRenderedImage(bufimg); BufferedImage imgTile = pimage.getAsBufferedImage( new Rectangle(xOffset, yOffset, width, height), pimage.getColorModel()); BufferedImage result = new BufferedImage( wantedWidth, wantedHeight, BufferedImage.TYPE_INT_ARGB); Graphics2D graf = result.createGraphics(); Color backgroundColor = (this.transparentColor!=null)?this.transparentColor:Color.white; graf.fillRect(0,0,wantedWidth, wantedHeight); int xTileOffset,yTileOffset; if (xOffset > 0){ xTileOffset = 0; } else { xTileOffset = (int)(offset2VisibleX * scaleX); } if (yOffset > 0){ yTileOffset = 0; } else { yTileOffset = (int)(offset2VisibleY * scaleY); } graf.drawImage(imgTile, xTileOffset, yTileOffset, imgTile.getWidth(), imgTile.getHeight(), backgroundColor, null); graf.dispose(); this.clearImageAndRaster(false); return result.getData(); } protected WorkbenchContext getWorkbenchContext(){ return (WorkbenchContext)this.getBlackboard().get(BLACKBOARD_KEY_WORKBENCHCONTEXT); } public static void setWorkbenchContext(WorkbenchContext wContext){ if (blackboard==null) blackboard = new Blackboard(); blackboard.put(BLACKBOARD_KEY_WORKBENCHCONTEXT, wContext); } public Rectangle getDrawingRectangle( double imgWidth, double imgHeight, Envelope imageEnv, Viewport viewport ) throws NoninvertibleTransformException{ Rectangle visible = viewport.getPanel().getVisibleRect(); Point2D upperLeftCorner = null; Point2D lowerRightCorner = null; try { upperLeftCorner = viewport.toViewPoint(new Coordinate(imageEnv.getMinX(), imageEnv.getMaxY())); lowerRightCorner = viewport.toViewPoint(new Coordinate(imageEnv.getMaxX(), imageEnv.getMinY())); } catch(java.awt.geom.NoninvertibleTransformException ne) { //logger.printError(ne.getLocalizedMessage()); ne.printStackTrace(); return null; } int visibleX1 = visible.x; int visibleY1 = visible.y; int visibleX2 = visibleX1 + visible.width; int visibleY2 = visibleY1 + visible.height; Coordinate upperLeftVisible = viewport.toModelCoordinate(nullpunkt); Coordinate lowerRightVisible = viewport.toModelCoordinate(new Point(visibleX2, visibleY2)); Envelope newVisibleEnv = new Envelope(upperLeftVisible.x, lowerRightVisible.x, upperLeftVisible.y, lowerRightVisible.y); Rectangle rect = this.getVisibleImageCoordinatesOfImage(imgWidth, imgHeight, newVisibleEnv, imageEnv); if (rect==null) return null; double scaledWidth = lowerRightCorner.getX() - upperLeftCorner.getX(); double scaledHeight = upperLeftCorner.getY() - lowerRightCorner.getY(); double scaleXImg2Canvas = scaledWidth / imgWidth; double scaleYImg2Canvas = scaledHeight / imgHeight; rect.width *= scaleXImg2Canvas; rect.height *= scaleYImg2Canvas; return rect; } protected Rectangle getVisibleImageCoordinatesOfImage( double imgWidth, double imgHeight, Envelope visible, Envelope imageEnv ){ double minVisibleX = Math.max(visible.getMinX(), imageEnv.getMinX()); double minVisibleY = Math.max(visible.getMinY(), imageEnv.getMinY()); double maxVisibleX = Math.min(visible.getMaxX(), imageEnv.getMaxX()); double maxVisibleY = Math.min(visible.getMaxY(), imageEnv.getMaxY()); double offset2VisibleX = imageEnv.getMinX() - visible.getMinX(); double offset2VisibleY = visible.getMaxY() - imageEnv.getMaxY(); double scaleX = imgWidth / imageEnv.getWidth(); double scaleY = imgHeight / imageEnv.getHeight(); if (offset2VisibleX >= 0){ this.xOffset = 0; } else { this.xOffset = (int)(-offset2VisibleX * scaleX); } if (offset2VisibleY >= 0){ this.yOffset = 0; } else { this.yOffset = (int)(-offset2VisibleY * scaleY); } int width = (int)((maxVisibleX-minVisibleX) * scaleX); int height = (int)((maxVisibleY-minVisibleY) * scaleY); if (width < imgWidth && height < imgHeight){ width += 1; height += 1; } if (width <= 0 || height <= 0){ return null; } return new Rectangle(this.xOffset, this.yOffset, width, height); } protected Rectangle getVisibleImageCoordinatesOfImage( PlanarImage img, Envelope visible, Envelope imageEnv ){ return this.getVisibleImageCoordinatesOfImage( img.getWidth(), img.getHeight(), visible, imageEnv ); } protected PlanarImage getVisiblePartOfTheImage( PlanarImage img, Rectangle desiredImageArea ){ if (desiredImageArea==null){ return null; } if ( desiredImageArea.width > 0 && desiredImageArea.height > 0 ){ if (desiredImageArea.width + desiredImageArea.x <= img.getWidth() && desiredImageArea.height + desiredImageArea.y <= img.getHeight() ) return PlanarImage.wrapRenderedImage( img.getAsBufferedImage( new Rectangle(desiredImageArea.x, desiredImageArea.y, desiredImageArea.width, desiredImageArea.height), img.getColorModel() )); //logger.printWarning("desired area invalid: " + (desiredImageArea.width + desiredImageArea.x) + ", " + (desiredImageArea.height + desiredImageArea.y) + "; image dimensions: " + img.getWidth() + ", " + img.getHeight()); } return null; } /** * Sets the image that will be shown in the map (also sets some interally used flags) *@param image image that will be shown in the map */ public void setImage(javax.media.jai.PlanarImage image) { this.image = image; origImageWidth = image.getWidth(); origImageHeight = image.getHeight(); imageSet = true; } public void setImageSet(boolean imageSet) { this.imageSet = imageSet; } public boolean isImageNull(){ return this.image == null; } /** * returns the image, this can be modified - i.e. is just a representation. *@return the image */ public PlanarImage getImageForDisplay(){ if (this.image == null) this.reLoadImage(); return this.image; } /** *@return true, if the image object was set at least once, else false */ public boolean isImageSet() { return imageSet; } /** * Returns the transparency level of the image. The transparencyLevel controlls the transparency level of the whole image (all pixels). It * is independent of the transparency color, that replaces a certain color in the image. * The transparencyLevel is expressed as a float within a range from 0.0 (no transparency) to 1.0 (full transparency). *@return the transparency level of the image */ public double getTransparencyLevel() { return transparencyLevel; } /** * Sets the transparency level of the image. This controlls the transparency level of the whole image (all pixels). It * is independent of the transparency color, that replaces a certain color in the image. * The transparencyLevel is expressed as a float within a range from 0.0 (no transparency) to 1.0 (full transparency). *@param transparencyLevel the transparency level of the image */ public void setTransparencyLevel(double transparencyLevel) { if (transparencyLevel != this.transparencyLevel){ this.transparencyLevel = transparencyLevel; if (this.isFiringAppearanceEvents()) this.fireAppearanceChanged(); } } /** * Sets the transparency level of the image. This controlls the transparency level of the whole image (all pixels). It * is independent of the transparency color, that replaces a certain color in the image. * The transparencyLevel is expressed as a percentage within a range from 0 (no transparency) to 100 (full transparency). *@param transparencyInPercent the transparency level of the image */ public void setTransparencyLevelInPercent(int transparencyInPercent) { double tLevel = transparencyInPercent/100.0; if (tLevel != this.transparencyLevel){ this.transparencyLevel = tLevel; if (this.isFiringAppearanceEvents()) this.fireAppearanceChanged(); } } /** * Gets the color which will be drawn with a zero opacity in the Jump map *@return color that will be replaced with transparent pixels */ public Color getTransparentColor() { return transparentColor; } /** * for java2xml */ public String getTransparentColorAsString() { if (this.getTransparentColor()==null) return "null"; String hexColor = Integer.toHexString(this.getTransparentColor().getRGB()); if (hexColor.length()>6){ hexColor = hexColor.substring(2); } return hexColor; } /** * for java2xml */ public void setTransparentColorAsString(String hexColorString) { if (hexColorString==null || hexColorString.equals("null")){ return; } int rgb = Integer.parseInt(hexColorString.toUpperCase(), 16); Color tColor = new Color(rgb); this.setTransparentColor(tColor); } /** * Sets the color which will be drawn with a zero opacity in the Jump map *@param transparentColor the color for transparency */ public void setTransparentColor(Color transparentColor) { if (this.transparentColor != transparentColor && (this.transparentColor==null || !this.transparentColor.equals(transparentColor))){ this.transparentColor = transparentColor; this.forceTotalRepaint(); if (this.isFiringAppearanceEvents()) this.fireAppearanceChanged(); } } /** * After this method was invoked, the image will be * completely re-rendered (not using caches) the next time. */ protected void forceTotalRepaint(){ this.visibleEnv = null; this.setImageProcessingMode(RasterImageLayer.MODE_NONE); } /** *@return the current offset (to the viewport's <code>(0,0)</code>) in x direction */ public int getXOffset() { return xOffset; } /** *@return the current offset (to the viewport's <code>(0,0)</code>) in y direction */ public int getYOffset() { return yOffset; } public static double getFreeRamFactor() { return freeRamFactor; } public static void setFreeRamFactor(double freeRamFactor) { //logger.printDebug("setting freeRamFactor to " + freeRamFactor); RasterImageLayer.freeRamFactor = freeRamFactor; RasterImageLayer.minRamToKeepFree = RasterImageLayer.availRAM * RasterImageLayer.freeRamFactor; RasterImageLayer.maxPixelsForFastDisplayMode = (int)((RasterImageLayer.availRAM - RasterImageLayer.minRamToKeepFree)/(1024*1024) * 3000); //logger.printDebug("maxPixelsForFastDisplayMode: " + maxPixelsForFastDisplayMode); } public static long getAvailRAM() { return availRAM; } public static int getMaxPixelsForFastDisplayMode() { return maxPixelsForFastDisplayMode; } public static double getMinRamToKeepFree() { return minRamToKeepFree; } /** * Sets the image's files name (if image is not to be keeped) - this needs to be set! *@param imageFileName the file name of the image */ public void setImageFileName(String imageFileName) { this.imageFileName = imageFileName; this.setNeedToKeepImage(false); } /** * *@return the file name of the image represented by this instance of the <code>RasterImageLayer</code> */ public String getImageFileName() { return imageFileName; } /** * check, if image will be keeped in RAM or if it will be reloaded from a file * if needed *@return true if image will be keeped in RAM, else false */ public boolean isNeedToKeepImage() { return needToKeepImage; } /** * toogle, if image will be keeped in RAM or if it will be reloaded from a file * if needed *@param needToKeepImage true if image is supposed be keeped in RAM, else false */ public void setNeedToKeepImage(boolean needToKeepImage) { this.needToKeepImage = needToKeepImage; } protected void finalize() throws Throwable { super.finalize(); this.flushImages(true); } /** *@return the height of the source image */ public int getOrigImageHeight() { return origImageHeight; } /** *@return the width of the source image */ public int getOrigImageWidth() { return origImageWidth; } /** * for java2xml *@param origImageHeight */ public void setOrigImageHeight(int origImageHeight) { this.origImageHeight = origImageHeight; } /** * for java2xml *@param origImageWidth */ public void setOrigImageWidth(int origImageWidth) { this.origImageWidth = origImageWidth; } /** * shows or hides the image in the Jump map *@param visible */ public void setVisible(boolean visible) { super.setVisible(visible); if (!visible) this.clearImageAndRaster(true); if (this.isFiringAppearanceEvents()) this.fireAppearanceChanged(); } /** * @see #firingAppearanceEvents *@return true if appearance events are fired automatically, false if not */ public boolean isFiringAppearanceEvents() { return firingAppearanceEvents; } /** * @see #firingAppearanceEvents *@param firingAppearanceEvents true if appearance events are to be fired automatically, false if not */ public void setFiringAppearanceEvents(boolean firingAppearanceEvents) { this.firingAppearanceEvents = firingAppearanceEvents; } // Metainformation stuff protected MetaDataMap metaInformation = null; public MetaDataMap getMetaInformation() { return metaInformation; } public void setMetaInformation(MetaDataMap metaInformation) { this.metaInformation = metaInformation; } /** * the original raster data values. For display use getImage(). * @return the rasterData */ public Raster getRasterData() { //if (rasterData == null) //-- [sstein Aug10th 2010] now reload every time but keep Style this.reLoadImageButKeepImageForDisplay(); return rasterData; } /** * to set the Raster data, use also setImage() * @param newRaster */ public void setRasterData(Raster newRaster) { rasterData = newRaster; setRasterDataChanged(true); } /** * @return the rasterDataChanged */ public boolean isRasterDataChanged() { return rasterDataChanged; } /** * @param rasterDataChanged the rasterDataChanged to set */ public void setRasterDataChanged(boolean rasterDataChanged) { this.rasterDataChanged = rasterDataChanged; } }