Revision: 6596
http://sourceforge.net/p/jump-pilot/code/6596
Author: michaudm
Date: 2020-10-12 19:19:38 +0000 (Mon, 12 Oct 2020)
Log Message:
-----------
Keep double parameters as long as possible (does not solve the pb described in
#507)
Modified Paths:
--------------
core/trunk/src/com/vividsolutions/jump/workbench/imagery/geoimg/GeoImage.java
Modified:
core/trunk/src/com/vividsolutions/jump/workbench/imagery/geoimg/GeoImage.java
===================================================================
---
core/trunk/src/com/vividsolutions/jump/workbench/imagery/geoimg/GeoImage.java
2020-10-12 15:05:32 UTC (rev 6595)
+++
core/trunk/src/com/vividsolutions/jump/workbench/imagery/geoimg/GeoImage.java
2020-10-12 19:19:38 UTC (rev 6596)
@@ -37,6 +37,7 @@
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
+import java.awt.geom.NoninvertibleTransformException;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.awt.image.renderable.ParameterBlock;
@@ -44,10 +45,15 @@
import javax.media.jai.JAI;
import javax.media.jai.RenderedOp;
+import javax.media.jai.operator.AffineDescriptor;
+import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Envelope;
+import com.vividsolutions.jts.geom.util.AffineTransformation;
+import com.vividsolutions.jts.geom.util.AffineTransformationBuilder;
import com.vividsolutions.jump.JUMPException;
import com.vividsolutions.jump.feature.Feature;
+import com.vividsolutions.jump.util.Timer;
import com.vividsolutions.jump.workbench.imagery.ReferencedImage;
import com.vividsolutions.jump.workbench.imagery.ReferencedImageException;
import com.vividsolutions.jump.workbench.model.Disposable;
@@ -57,7 +63,7 @@
public class GeoImage implements ReferencedImage, Disposable, AlphaSetting {
private GeoReferencedRaster gtr;
private int alpha = 255;
- private float last_scale;
+ private double last_scale;
private RenderedOp last_scale_img;
private Envelope last_img_env;
private RenderedImage last_rendering;
@@ -92,6 +98,7 @@
public synchronized void paint(Feature f, java.awt.Graphics2D g, Viewport
viewport)
throws ReferencedImageException {
+ //long t0 = Timer.now();
try {
// update image envelope, either use geometry's or image's
// this allows moving the image via geometry movement
@@ -109,17 +116,17 @@
// + Integer.toHexString(img.hashCode()));
// get current scale
- final float scale = (float) viewport.getScale();
+ final double scale = viewport.getScale();
// get current viewport area
Envelope envModel_viewport = viewport.getEnvelopeInModelCoordinates();
// if nothing changed, no reason to rerender the whole shebang
// this is mainly the case when OJ last and regained focus
- if (last_scale == scale && last_img_env instanceof Envelope
- && last_img_env.equals(envImage) && last_vwp_env instanceof Envelope
+ if (last_scale == scale && last_img_env != null
+ && last_img_env.equals(envImage) && last_vwp_env != null
&& last_vwp_env.equals(envModel_viewport)
- && last_rendering instanceof RenderedImage
- && last_transform instanceof AffineTransform) {
+ && last_rendering != null
+ && last_transform != null) {
draw(g, null);
return;
}
@@ -132,7 +139,7 @@
// reuse a cached version if scale and img_envelope didn't changed
// speeds up panning, window resizing
if (last_scale == scale && last_scale_img != null
- && last_img_env instanceof Envelope
+ && last_img_env != null
&& last_img_env.equals(envImage)) {
img = last_scale_img;
// System.out.println("GI: USE SCALE CACHE");
@@ -140,8 +147,8 @@
// System.out.println("GI: NO SCALE CACHE");
// First, scale the original image
- float scaleX = scale * (float) gtr.getDblModelUnitsPerRasterUnit_X();
- float scaleY = scale * (float) gtr.getDblModelUnitsPerRasterUnit_Y();
+ double scaleX = scale * gtr.getDblModelUnitsPerRasterUnit_X();
+ double scaleY = scale * gtr.getDblModelUnitsPerRasterUnit_Y();
// calculate predicted dimensions
double scaledW = scaleX * src_img.getWidth();
@@ -157,7 +164,7 @@
// we cache an overview here for big pictures
// speeds up situations when the whole picture is shown
- float scaleX_toUse, scaleY_toUse;
+ double scaleX_toUse, scaleY_toUse;
RenderedImage scale_src_img;
if ((imgW > 2000 || imgH > 2000) && scaledW < 2000 && scaledH < 2000
) {
// System.out.println("GI: USE FULL SCALE CACHE");
@@ -165,9 +172,9 @@
// this is faster than having JAI create it from scratch from big
datasets
if (full_scale_img == null) {
if (imgW > imgH) {
- full_scale = 1 / (imgW / 2000d);
+ full_scale = 2000d / imgW;
} else {
- full_scale = 1 / (imgH / 2000d);
+ full_scale = 2000d / imgH;
}
// subsample average gives a smoothly resized image
pb = new ParameterBlock();
@@ -178,14 +185,14 @@
// System.out.println("GI full scale img: "
// + full_scale_img.getWidth());
}
- scaleX_toUse = (float) scaleX / (float) full_scale;
- scaleY_toUse = (float) scaleY / (float) full_scale;
+ scaleX_toUse = scaleX / full_scale;
+ scaleY_toUse = scaleY / full_scale;
scale_src_img = full_scale_img;
}
// scale the original
else{
- scaleX_toUse = (float) scaleX;
- scaleY_toUse = (float) scaleY;
+ scaleX_toUse = scaleX;
+ scaleY_toUse = scaleY;
scale_src_img = src_img;
}
@@ -195,8 +202,8 @@
// so use slow and qualitative inferior bicubic instead
// or NOT, to f**g slow, use default interpolation
if (scaleX > 0.1 || scaleY > 0.1) {
- pb.add(scaleX_toUse);
- pb.add(scaleY_toUse);
+ pb.add((float)scaleX_toUse);
+ pb.add((float)scaleY_toUse);
pb.add(0f);
pb.add(0f);
// Interpolation interp = Interpolation
@@ -204,8 +211,8 @@
// pb.add(interp); // add interpolation method
img = JAI.create("scale", pb, hints);
} else {
- pb.add((double) (scaleX_toUse));
- pb.add((double) (scaleY_toUse));
+ pb.add(scaleX_toUse);
+ pb.add(scaleY_toUse);
img = JAI.create("subsampleaverage", pb, hints);
}
@@ -244,13 +251,13 @@
double ratio_cropW = envModel_viewport.getWidth() / envImage.getWidth();
double ratio_cropH = envModel_viewport.getHeight() /
envImage.getHeight();
- float raster_cropX = (int) (ratio_cropX * img.getWidth());
- float raster_cropY = (int) (ratio_cropY * img.getHeight());
- float raster_cropW = (int) (ratio_cropW * img.getWidth());
- float raster_cropH = (int) (ratio_cropH * img.getHeight());
+ double raster_cropX = ratio_cropX * img.getWidth();
+ double raster_cropY = ratio_cropY * img.getHeight();
+ double raster_cropW = ratio_cropW * img.getWidth();
+ double raster_cropH = ratio_cropH * img.getHeight();
- float raster_offsetX = 0;
- float raster_offsetY = 0;
+ double raster_offsetX = 0;
+ double raster_offsetY = 0;
if (raster_cropX < 0) {
raster_offsetX = -raster_cropX;
@@ -260,24 +267,30 @@
raster_offsetY = -raster_cropY;
raster_cropY = 0;
}
+ raster_cropX = Math.min((float)raster_cropX, (float)img.getWidth());
+ raster_cropY = Math.min((float)raster_cropY, (float)img.getHeight());
raster_cropW = Math
- .min(raster_cropW, img.getWidth() - (int) raster_cropX);
- raster_cropH = Math.min(raster_cropH, img.getHeight()
- - (int) raster_cropY);
+ .min((float)raster_cropW, (float)img.getWidth() - /*(int)*/
raster_cropX);
+ raster_cropH = Math.min((float)raster_cropH, (float)img.getHeight()
+ - /*(int)*/ raster_cropY);
pb = new ParameterBlock();
pb.addSource(img);
- pb.add(raster_cropX);
- pb.add(raster_cropY);
- pb.add(raster_cropW);
- pb.add(raster_cropH);
+ //System.out.println("cropx " + (float)raster_cropX);
+ //System.out.println("cropy " + (float)raster_cropY);
+ //System.out.println("cropw " + (float)raster_cropW + " " +
(img.getWidth() - /*(int)*/ raster_cropX));
+ //System.out.println("croph " + (float)raster_cropH + " " +
(img.getHeight() - /*(int)*/ raster_cropY));
+ pb.add((float)raster_cropX);
+ pb.add((float)raster_cropY);
+ pb.add((float)raster_cropW);
+ pb.add((float)raster_cropH);
img = JAI.create("crop", pb, null);
// move the image to the model coordinates
pb = new ParameterBlock();
pb.addSource(img);
- pb.add(raster_offsetX - img.getMinX());
- pb.add(raster_offsetY - img.getMinY());
+ pb.add((float)(raster_offsetX - img.getMinX()));
+ pb.add((float)(raster_offsetY - img.getMinY()));
img = JAI.create("translate", pb, null);
// cache the current rendering here as used in the
@@ -288,6 +301,7 @@
// eventually draw the image, let g render the chain
draw(g, img);
+ //System.out.printf("Display at %f in %d ms%n", scale,
Timer.milliSecondsSince(t0));
} catch (Exception ex) {
throw new ReferencedImageException(ex);
@@ -294,6 +308,77 @@
}
}
+ // [mmichaud 2020-10-12] try to make image display more precise using
double-based
+ // affine transform, but the code does not take advanatage of jai subsample
used in
+ // the previous code and is much slower
+ //RenderedImage cached2000px = null;
+ //public synchronized void paint(Feature f, java.awt.Graphics2D g, Viewport
viewport)
+ // throws ReferencedImageException {
+ // long t0 = Timer.now();
+ // long t1 = 0L;
+ // // Image enveloppe in model coordinates
+ // Envelope imageEnv = gtr.getEnvelope(f);
+ // RenderedOp op = gtr.getRenderedOp();
+ // RenderedImage im = op;
+ // RenderingHints hints = gtr.createCacheRenderingHints();
+ //
+ // // Size of an image pixel in the Model (ground coordinates)
+ // double pixelSizeInModelX = imageEnv.getWidth()/op.getWidth();
+ // double pixelSizeInModelY = imageEnv.getHeight()/op.getHeight();
+ // double scale = viewport.getScale();
+ // // Size of an image pixel in the screen model (number of screen pixel
for one image pixel)
+ // double pixelSizeInViewX = pixelSizeInModelX * scale;
+ // double pixelSizeInViewY = pixelSizeInModelY * scale;
+ // // Short circuit : if the full image is < 1 screen pixel, return
+ // if (pixelSizeInViewX*im.getWidth() < 0.5 &&
pixelSizeInViewY*im.getHeight() < 0.5) {
+ // System.out.println("Full image < 1 px");
+ // return;
+ // }
+ //
+ // if ((im.getWidth() > 2000 || im.getHeight() > 2000) && pixelSizeInViewX
< 1 && pixelSizeInViewY < 1) {
+ // if (cached2000px == null) {
+ // full_scale = 2000d / Math.max(im.getWidth(), im.getHeight());
+ // ParameterBlock pb = new ParameterBlock();
+ // pb.addSource(im);
+ // pb.add(full_scale); // x scale factor
+ // pb.add(full_scale); // y scale factor
+ // cached2000px = JAI.create("subsampleaverage", pb, null);
+ // }
+ // im = cached2000px;
+ // }
+ //
+ // System.out.println("Image " + im.getWidth() + " x " + im.getHeight());
+ //
+ // try {
+ // AffineTransform model2view = viewport.getModelToViewTransform();
+ // AffineTransformation imageToModel = new AffineTransformationBuilder(
+ // new Coordinate(0.0, 0.0),
+ // new Coordinate(im.getWidth(), 0.0),
+ // new Coordinate(0.0, im.getHeight()),
+ // new Coordinate(imageEnv.getMinX(), imageEnv.getMaxY()),
+ // new Coordinate(imageEnv.getMaxX(), imageEnv.getMaxY()),
+ // new Coordinate(imageEnv.getMinX(), imageEnv.getMinY())
+ // ).getTransformation();
+ //
+ // AffineTransform image2view = new AffineTransform(
+ // imageToModel.getMatrixEntries()[0],
+ // imageToModel.getMatrixEntries()[3],
+ // imageToModel.getMatrixEntries()[1],
+ // imageToModel.getMatrixEntries()[4],
+ // imageToModel.getMatrixEntries()[2],
+ // imageToModel.getMatrixEntries()[5]
+ // );
+ //
+ // image2view.preConcatenate(model2view);
+ // im = AffineDescriptor.create(im,image2view, null,null, hints);
+ // g.drawRenderedImage(im, new AffineTransform());
+ //
+ // System.out.printf("Display at %f (jai %d) (%dx%d) in %d ms%n", scale,
t1, im.getWidth(), im.getHeight(), Timer.milliSecondsSince(t0));
+ // } catch (NoninvertibleTransformException ex) {
+ // throw new ReferencedImageException(ex);
+ // }
+ //}
+
private void draw(Graphics2D g, RenderedImage img) {
Composite composite = g.getComposite();
// setup transparency
@@ -302,7 +387,7 @@
// The image has been translated and scaled by JAI
// already. Just draw it with an identity transformation.
AffineTransform aft;
- if (img instanceof RenderedImage){
+ if (img != null) {
aft = new AffineTransform();
}
// no img given? paint cached last rendering again
_______________________________________________
Jump-pilot-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/jump-pilot-devel