Changeset 11897 in josm for trunk/src/org
- Timestamp:
- 2017-04-13T15:14:20+02:00 (8 years ago)
- Location:
- trunk/src/org/openstreetmap/josm
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/gui/layer/imagery/ReprojectionTile.java
r11894 r11897 103 103 double scaleMapView = Main.map.mapView.getScale(); 104 104 ImageWarp.Interpolation interpolation; 105 switch (Main.pref.get("imagery.warp. interpolation", "bilinear")) {105 switch (Main.pref.get("imagery.warp.pixel-interpolation", "bilinear")) { 106 106 case "nearest_neighbor": 107 107 interpolation = ImageWarp.Interpolation.NEAREST_NEIGHBOR; … … 148 148 (pbTargetAligned.maxNorth - en11Current.north()) / scale); 149 149 150 ImageWarp.PointTransform transform; 151 int stride = Main.pref.getInteger("imagery.warp.projection-interpolation.stride", 7); 152 if (stride > 0) { 153 transform = new ImageWarp.GridTransform(pointTransform, stride); 154 } else { 155 transform = pointTransform; 156 } 150 157 BufferedImage imageOut = ImageWarp.warp( 151 imageIn, getDimension(pbTargetAligned, scale), pointTransform,152 interpolation);158 imageIn, getDimension(pbTargetAligned, scale), 159 transform, interpolation); 153 160 synchronized (this) { 154 161 this.image = imageOut; -
trunk/src/org/openstreetmap/josm/tools/ImageWarp.java
r11896 r11897 6 6 import java.awt.geom.Rectangle2D; 7 7 import java.awt.image.BufferedImage; 8 import java.util.HashMap; 9 import java.util.HashSet; 10 import java.util.Map; 11 import java.util.Set; 8 12 9 13 /** … … 20 24 public interface PointTransform { 21 25 Point2D transform(Point2D pt); 26 } 27 28 /** 29 * Wrapper that optimizes a given {@link ImageWarp.PointTransform}. 30 * 31 * It does so by spanning a grid with certain step size. It will invoke the 32 * potentially expensive master transform only at those grid points and use 33 * bilinear interpolation to approximate transformed values in between. 34 * <p> 35 * For memory optimization, this class assumes that rows are more or less scanned 36 * one-by-one as is done in {@link ImageWarp#warp}. I.e. this transform is <em>not</em> 37 * random access in the y coordinate. 38 */ 39 public static class GridTransform implements ImageWarp.PointTransform { 40 41 private final double stride; 42 private final ImageWarp.PointTransform trfm; 43 44 private final Map<Integer, Map<Integer, Point2D>> cache; 45 46 private static final boolean CONSISTENCY_TEST = false; 47 private final Set<Integer> deletedRows; 48 49 /** 50 * Create a new GridTransform. 51 * @param trfm the master transform, that needs to be optimized 52 * @param stride step size 53 */ 54 public GridTransform(ImageWarp.PointTransform trfm, double stride) { 55 this.trfm = trfm; 56 this.stride = stride; 57 this.cache = new HashMap<>(); 58 if (CONSISTENCY_TEST) { 59 deletedRows = new HashSet<>(); 60 } else { 61 deletedRows = null; 62 } 63 } 64 65 @Override 66 public Point2D transform(Point2D pt) { 67 int xIdx = (int) Math.floor(pt.getX() / stride); 68 int yIdx = (int) Math.floor(pt.getY() / stride); 69 double dx = pt.getX() / stride - xIdx; 70 double dy = pt.getY() / stride - yIdx; 71 Point2D value00 = getValue(xIdx, yIdx); 72 Point2D value01 = getValue(xIdx, yIdx + 1); 73 Point2D value10 = getValue(xIdx + 1, yIdx); 74 Point2D value11 = getValue(xIdx + 1, yIdx + 1); 75 double valueX = (value00.getX() * (1-dx) + value10.getX() * dx) * (1-dy) + 76 (value01.getX() * (1-dx) + value11.getX() * dx) * dy; 77 double valueY = (value00.getY() * (1-dx) + value10.getY() * dx) * (1-dy) + 78 (value01.getY() * (1-dx) + value11.getY() * dx) * dy; 79 return new Point2D.Double(valueX, valueY); 80 } 81 82 private Point2D getValue(int xIdx, int yIdx) { 83 Map<Integer, Point2D> row = getRow(yIdx); 84 Point2D val = row.get(xIdx); 85 if (val == null) { 86 val = trfm.transform(new Point2D.Double(xIdx * stride, yIdx * stride)); 87 row.put(xIdx, val); 88 } 89 return val; 90 } 91 92 private Map<Integer, Point2D> getRow(int yIdx) { 93 cleanUp(yIdx - 2); 94 Map<Integer, Point2D> row = cache.get(yIdx); 95 if (row == null) { 96 row = new HashMap<>(); 97 cache.put(yIdx, row); 98 if (CONSISTENCY_TEST) { 99 // should not create a row that has been deleted before 100 if (deletedRows.contains(yIdx)) throw new AssertionError(); 101 // only ever cache 2 rows at once 102 if (cache.size() > 2) throw new AssertionError(); 103 } 104 } 105 return row; 106 } 107 108 // remove rows from cache that will no longer be used 109 private void cleanUp(int yIdx) { 110 Map<Integer, Point2D> del = cache.remove(yIdx); 111 if (CONSISTENCY_TEST && del != null) { 112 // should delete each row only once 113 if (deletedRows.contains(yIdx)) throw new AssertionError(); 114 deletedRows.add(yIdx); 115 } 116 } 22 117 } 23 118
Note:
See TracChangeset
for help on using the changeset viewer.