001: package com.vividsolutions.jump.workbench.imagery.geotiff;
002:
003: import java.awt.AlphaComposite;
004: import java.awt.Graphics2D;
005: import java.awt.geom.AffineTransform;
006: import java.awt.image.renderable.ParameterBlock;
007:
008: import javax.media.jai.JAI;
009: import javax.media.jai.RenderedOp;
010:
011: import com.vividsolutions.jts.geom.Envelope;
012: import com.vividsolutions.jump.workbench.ui.Viewport;
013:
014: public class RasterPainter {
015: GeoReferencedRaster geoRaster;
016: Envelope envModel_viewportCached;
017: double scaleCached;
018: RenderedOp imgScaled;
019: RenderedOp imgWindow;
020: RenderedOp imgRescaled;
021:
022: // Rescaling parameters
023: final static double DEFAULT_RESCALINGCONSTANT = 1;
024: final static double DEFAULT_RESCALINGOFFSET = 0;
025: double rescalingConstant = DEFAULT_RESCALINGCONSTANT;
026: double rescalingOffset = DEFAULT_RESCALINGOFFSET;
027:
028: // private final int VIEWPORT_MINX = 0;
029: // private final int VIEWPORT_MINY = 0;
030:
031: boolean enabled = true;
032:
033: public RasterPainter(GeoReferencedRaster geoRaster) {
034: this .geoRaster = geoRaster;
035: }
036:
037: public void setRescalingConstant(double x) {
038: rescalingConstant = x;
039: }
040:
041: public void setRescalingOffset(double x) {
042: rescalingOffset = x;
043: }
044:
045: /**
046: * @param image
047: * @param constant
048: * @param offset
049: * @return
050: */
051: private RenderedOp rescale(RenderedOp image, double constant,
052: double offset) {
053: // If constant and offset equal to default values, don't do
054: // anything, saves time (hopefully).
055: if (constant == DEFAULT_RESCALINGCONSTANT
056: && offset == DEFAULT_RESCALINGOFFSET)
057: return image;
058: else {
059: int bands = imgWindow.getNumBands();
060: double[] constants = new double[bands];
061: double[] offsets = new double[bands];
062: for (int i = 0; i < bands; i++) {
063: constants[i] = constant;
064: offsets[i] = offset;
065: }
066: ParameterBlock pb = new ParameterBlock();
067: pb.addSource(image);
068: pb.add(constants);
069: pb.add(offsets);
070: return JAI.create("rescale", pb, null);
071: }
072: }
073:
074: /**
075: * @param image
076: * @return
077: */
078: private RenderedOp rescale(RenderedOp image) {
079: return rescale(image, rescalingConstant, rescalingOffset);
080: }
081:
082: /**
083: * @param viewport
084: * @return @throws
085: * Exception
086: */
087: private RenderedOp getWindow(Viewport viewport) throws Exception {
088: // Wat is de gewenste uitsnede in model-coordinaten ?
089: Envelope envModel_viewport = viewport
090: .getEnvelopeInModelCoordinates();
091:
092: if (envModel_viewportCached == null
093: || !envModel_viewportCached.equals(envModel_viewport)) {
094: // Most images perform better with calculateWindow2.
095: // Geomedia/USSampleimage.tif perform better with
096: // calculateWindow however. calculateWindow2 shows
097: // better when panning.
098: imgWindow = calculateWindow2(viewport, envModel_viewport);
099: }
100:
101: return imgWindow;
102: }
103:
104: private void scaleImage(double scale) throws Exception {
105: double scaleX = scale
106: * geoRaster.getDblModelUnitsPerRasterUnit_X();
107: double scaleY = scale
108: * geoRaster.getDblModelUnitsPerRasterUnit_Y();
109:
110: ParameterBlock pb = new ParameterBlock();
111: pb.addSource(geoRaster.getImage());
112: pb.add((float) scaleX);
113: pb.add((float) scaleY);
114: pb.add(0f);
115: pb.add(0f);
116: imgScaled = JAI.create("scale", pb, null);
117:
118: // (new TestFrame(imgScaled)).show();
119: }
120:
121: private RenderedOp calculateWindow2(Viewport viewport,
122: Envelope envModel_viewport) throws Exception {
123: // First, scale the original image if necessary.
124: final double scale = viewport.getScale();
125: if (scale != scaleCached) {
126: scaleImage(scale);
127: scaleCached = scale;
128: }
129:
130: // Next, crop the part which is needed out of the
131: // scaled image.
132: double ratio_cropX = (envModel_viewport.getMinX() - geoRaster
133: .getEnvelope().getMinX())
134: / geoRaster.getEnvelope().getWidth();
135: double ratio_cropY = (geoRaster.getEnvelope().getMaxY() - envModel_viewport
136: .getMaxY())
137: / geoRaster.getEnvelope().getHeight();
138: double ratio_cropW = envModel_viewport.getWidth()
139: / geoRaster.getEnvelope().getWidth();
140: double ratio_cropH = envModel_viewport.getHeight()
141: / geoRaster.getEnvelope().getHeight();
142:
143: float raster_cropX = (int) (ratio_cropX * imgScaled.getWidth());
144: float raster_cropY = (int) (ratio_cropY * imgScaled.getHeight());
145: float raster_cropW = (int) (ratio_cropW * imgScaled.getWidth());
146: float raster_cropH = (int) (ratio_cropH * imgScaled.getHeight());
147:
148: float raster_offsetX = 0;
149: float raster_offsetY = 0;
150:
151: if (raster_cropX < 0) {
152: raster_offsetX = -raster_cropX;
153: raster_cropX = 0;
154: }
155: if (raster_cropY < 0) {
156: raster_offsetY = -raster_cropY;
157: raster_cropY = 0;
158: }
159: raster_cropW = Math.min(raster_cropW, imgScaled.getWidth()
160: - (int) raster_cropX);
161: raster_cropH = Math.min(raster_cropH, imgScaled.getHeight()
162: - (int) raster_cropY);
163:
164: ParameterBlock pb = new ParameterBlock();
165: pb.addSource(imgScaled);
166: pb.add(raster_cropX);
167: pb.add(raster_cropY);
168: pb.add(raster_cropW);
169: pb.add(raster_cropH);
170: imgWindow = JAI.create("crop", pb, null);
171:
172: // imgWindow = imgScaled;
173:
174: pb = new ParameterBlock();
175: pb.addSource(imgWindow);
176: pb.add(raster_offsetX - imgWindow.getMinX());
177: pb.add(raster_offsetY - imgWindow.getMinY());
178: imgWindow = JAI.create("translate", pb, null);
179:
180: return imgWindow;
181: }
182:
183: /**
184: *
185: */
186: public void paint(Graphics2D g, Viewport viewport) throws Exception {
187: // Get the image for the current viewport.
188: RenderedOp imgWindowed = getWindow(viewport);
189: if (imgWindowed == null)
190: return;
191:
192: // Adjust brightness and contrast of this image.
193: RenderedOp imgRescaled = rescale(imgWindowed);
194: if (imgRescaled == null)
195: return;
196:
197: g.setComposite(AlphaComposite.SrcOver);
198: // The image has been translated and scaled by JAI
199: // allready. Just draw it with an identity transformation.
200: g.drawRenderedImage(imgRescaled, new AffineTransform());
201: }
202:
203: /**
204: *
205: */
206: public void setEnabled(boolean enabled) {
207: this .enabled = enabled;
208: }
209:
210: /**
211: * @return Returns the rescalingConstant.
212: */
213: public double getRescalingConstant() {
214: return rescalingConstant;
215: }
216:
217: /**
218: * @return Returns the rescalingOffset.
219: */
220: public double getRescalingOffset() {
221: return rescalingOffset;
222: }
223:
224: }
|