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
Jump-pilot-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/jump-pilot-devel

Reply via email to