hey Mike, how about cropping first and scaling only the part shown?.. ede
On October 12, 2020 9:19:38 PM GMT+02:00, jump-pilot-svn--- via Jump-pilot-devel <jump-pilot-devel@lists.sourceforge.net> wrote: >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 _______________________________________________ Jump-pilot-devel mailing list Jump-pilot-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/jump-pilot-devel