diff --git a/src/org/openstreetmap/josm/gui/mappaint/styleelement/MapImage.java b/src/org/openstreetmap/josm/gui/mappaint/styleelement/MapImage.java
index 963b42bab..c921a2217 100644
|
a
|
b
|
private Image getImage() {
|
| 189 | 189 | ImageIcon noIcon = MapPaintStyles.getNoIconIcon(source); |
| 190 | 190 | img = noIcon == null ? null : noIcon.getImage(); |
| 191 | 191 | } else { |
| 192 | | img = rescale(result.getImageIcon(new Dimension(width, height)).getImage()); |
| | 192 | img = result.getImageIcon(new Dimension(width, height)).getImage(); |
| | 193 | if (img != null && mustRescale(img)) { |
| | 194 | // Scale down large images to 16x16 pixels if no size is explicitly specified |
| | 195 | img = result.getImageIconBounded(ImageProvider.ImageSizes.MAP.getImageDimension()).getImage(); |
| | 196 | } |
| 193 | 197 | } |
| 194 | 198 | if (temporary) { |
| 195 | 199 | disabledImgCache = null; |
| … |
… |
public BoxProvider getBoxProvider() {
|
| 300 | 304 | return new MapImageBoxProvider(); |
| 301 | 305 | } |
| 302 | 306 | |
| 303 | | /** |
| 304 | | * Rescale excessively large images. |
| 305 | | * @param image the unscaled image |
| 306 | | * @return The scaled down version to 16x16 pixels if the image height and width exceeds 48 pixels and no size has been explicitly specified |
| 307 | | */ |
| 308 | | private Image rescale(Image image) { |
| 309 | | if (image == null) return null; |
| 310 | | // Scale down large (.svg) images to 16x16 pixels if no size is explicitly specified |
| 311 | | if (mustRescale(image)) { |
| 312 | | return ImageProvider.createBoundedImage(image, 16); |
| 313 | | } else { |
| 314 | | return image; |
| 315 | | } |
| 316 | | } |
| 317 | | |
| 318 | 307 | private boolean mustRescale(Image image) { |
| 319 | 308 | return autoRescale && width == -1 && image.getWidth(null) > MAX_SIZE |
| 320 | 309 | && height == -1 && image.getHeight(null) > MAX_SIZE; |
diff --git a/src/org/openstreetmap/josm/tools/ImageProvider.java b/src/org/openstreetmap/josm/tools/ImageProvider.java
index 29a55dbe6..67d424bcd 100644
|
a
|
b
|
public ImageIcon get() {
|
| 660 | 660 | Logging.trace("get {0} from {1}", this, Thread.currentThread()); |
| 661 | 661 | } |
| 662 | 662 | if (virtualMaxWidth != -1 || virtualMaxHeight != -1) |
| 663 | | return ir.getImageIcon(new Dimension(virtualMaxWidth, virtualMaxHeight), multiResolution, ImageResizeMode.BOUNDED); |
| | 663 | return ir.getImageIcon(new Dimension(virtualMaxWidth, virtualMaxHeight), multiResolution, null); |
| 664 | 664 | else |
| 665 | 665 | return ir.getImageIcon(new Dimension(virtualWidth, virtualHeight), multiResolution, ImageResizeMode.AUTO); |
| 666 | 666 | } |
| … |
… |
static BufferedImage createImageFromSvg(SVGDiagram svg, Dimension dim, ImageResi
|
| 1489 | 1489 | Logging.error("createImageFromSvg: {0} {1} sourceWidth={2} sourceHeight={3}", svg.getXMLBase(), dim, sourceWidth, sourceHeight); |
| 1490 | 1490 | return null; |
| 1491 | 1491 | } |
| 1492 | | if (resizeMode == ImageResizeMode.BOUNDED) { |
| 1493 | | resizeMode = ImageResizeMode.BOUNDED_UPSCALE; |
| 1494 | | } |
| 1495 | 1492 | return resizeMode.createBufferedImage(dim, new Dimension((int) sourceWidth, (int) sourceHeight), g -> { |
| 1496 | 1493 | try { |
| 1497 | 1494 | synchronized (getSvgUniverse()) { |
diff --git a/src/org/openstreetmap/josm/tools/ImageResizeMode.java b/src/org/openstreetmap/josm/tools/ImageResizeMode.java
index 2ea8d1e68..d1bcabc2a 100644
|
a
|
b
|
|
| 13 | 13 | */ |
| 14 | 14 | enum ImageResizeMode { |
| 15 | 15 | |
| | 16 | /** |
| | 17 | * Calculate proportional dimensions that best fit into the target width and height, retain aspect ratio |
| | 18 | */ |
| 16 | 19 | AUTO { |
| 17 | 20 | @Override |
| 18 | 21 | Dimension computeDimension(Dimension dim, Dimension icon) { |
| … |
… |
Dimension computeDimension(Dimension dim, Dimension icon) {
|
| 24 | 27 | return new Dimension(Math.max(1, icon.width * dim.height / icon.height), dim.height); |
| 25 | 28 | } else if (dim.height == -1) { |
| 26 | 29 | return new Dimension(dim.width, Math.max(1, icon.height * dim.width / icon.width)); |
| | 30 | } else if (icon.getWidth() / dim.getWidth() > icon.getHeight() / dim.getHeight()) { |
| | 31 | return computeDimension(new Dimension(dim.width, -1), icon); |
| 27 | 32 | } else { |
| 28 | | return dim; |
| | 33 | return computeDimension(new Dimension(-1, dim.height), icon); |
| 29 | 34 | } |
| 30 | 35 | } |
| 31 | 36 | }, |
| 32 | 37 | |
| | 38 | /** |
| | 39 | * Calculate dimensions for the largest image that fit within the bounding box, retain aspect ratio |
| | 40 | */ |
| 33 | 41 | BOUNDED { |
| 34 | | @Override |
| 35 | | Dimension computeDimension(Dimension dim, Dimension icon) { |
| 36 | | final int maxWidth = Math.min(dim.width, icon.width); |
| 37 | | final int maxHeight = Math.min(dim.height, icon.height); |
| 38 | | return BOUNDED_UPSCALE.computeDimension(new Dimension(maxWidth, maxHeight), icon); |
| 39 | | } |
| 40 | | }, |
| 41 | | |
| 42 | | BOUNDED_UPSCALE { |
| 43 | 42 | @Override |
| 44 | 43 | Dimension computeDimension(Dimension dim, Dimension icon) { |
| 45 | 44 | CheckParameterUtil.ensureThat((dim.width > 0 || dim.width == -1) && (dim.height > 0 || dim.height == -1), |
| 46 | 45 | () -> dim + " is invalid"); |
| 47 | | final int maxWidth = dim.width; |
| 48 | | final int maxHeight = dim.height; |
| 49 | | final Dimension spec; |
| 50 | | if (maxWidth == -1 || maxHeight == -1) { |
| 51 | | spec = dim; |
| 52 | | } else if (icon.getWidth() / maxWidth > icon.getHeight() / maxHeight) { |
| 53 | | spec = new Dimension(maxWidth, -1); |
| 54 | | } else { |
| 55 | | spec = new Dimension(-1, maxHeight); |
| 56 | | } |
| 57 | | return AUTO.computeDimension(spec, icon); |
| | 46 | final int maxWidth = Math.min(dim.width, icon.width); |
| | 47 | final int maxHeight = Math.min(dim.height, icon.height); |
| | 48 | return AUTO.computeDimension(new Dimension(maxWidth, maxHeight), icon); |
| 58 | 49 | } |
| 59 | 50 | }, |
| 60 | 51 | |
| | 52 | /** |
| | 53 | * Position an appropriately scaled image within the bounding box, retain aspect ratio |
| | 54 | */ |
| 61 | 55 | PADDED { |
| 62 | 56 | @Override |
| 63 | 57 | Dimension computeDimension(Dimension dim, Dimension icon) { |
diff --git a/src/org/openstreetmap/josm/tools/ImageResource.java b/src/org/openstreetmap/josm/tools/ImageResource.java
index 59d9834d1..f710b7f30 100644
|
a
|
b
|
public ImageResource setDisabled(boolean disabled) {
|
| 101 | 101 | */ |
| 102 | 102 | public void attachImageIcon(AbstractAction a) { |
| 103 | 103 | Dimension iconDimension = ImageProvider.ImageSizes.SMALLICON.getImageDimension(); |
| 104 | | ImageIcon icon = getImageIconBounded(iconDimension); |
| | 104 | ImageIcon icon = getImageIcon(iconDimension); |
| 105 | 105 | a.putValue(Action.SMALL_ICON, icon); |
| 106 | 106 | |
| 107 | 107 | iconDimension = ImageProvider.ImageSizes.LARGEICON.getImageDimension(); |
| 108 | | icon = getImageIconBounded(iconDimension); |
| | 108 | icon = getImageIcon(iconDimension); |
| 109 | 109 | a.putValue(Action.LARGE_ICON_KEY, icon); |
| 110 | 110 | } |
| 111 | 111 | |
| … |
… |
public ImageIcon getImageIcon() {
|
| 140 | 140 | * @see #getImageIconBounded(java.awt.Dimension) |
| 141 | 141 | */ |
| 142 | 142 | public ImageIcon getImageIcon(Dimension dim) { |
| 143 | | return getImageIcon(dim, true, ImageResizeMode.AUTO); |
| | 143 | return getImageIcon(dim, true, null); |
| 144 | 144 | } |
| 145 | 145 | |
| 146 | 146 | /** |
| … |
… |
ImageIcon getImageIconAlreadyScaled(Dimension dim, boolean multiResolution, bool
|
| 174 | 174 | CheckParameterUtil.ensureThat((dim.width > 0 || dim.width == -1) && (dim.height > 0 || dim.height == -1), |
| 175 | 175 | () -> dim + " is invalid"); |
| 176 | 176 | |
| | 177 | if (resizeMode == null && svg != null) { |
| | 178 | // upscale SVG icons |
| | 179 | resizeMode = ImageResizeMode.AUTO; |
| | 180 | } else if (resizeMode == null) { |
| | 181 | resizeMode = ImageResizeMode.BOUNDED; |
| | 182 | } |
| 177 | 183 | final int cacheKey = resizeMode.cacheKey(dim); |
| 178 | 184 | BufferedImage img = imgCache.get(cacheKey); |
| 179 | 185 | if (img == null) { |
diff --git a/test/functional/org/openstreetmap/josm/tools/ImageProviderTest.java b/test/functional/org/openstreetmap/josm/tools/ImageProviderTest.java
index e4b0bd20e..a318f11c2 100644
|
a
|
b
|
public void testImageIcon() throws IOException {
|
| 170 | 170 | ImageResource resource = new ImageProvider("presets/misc/housenumber_small").getResource(); |
| 171 | 171 | testImage(12, 9, "housenumber_small-AUTO-null", resource.getImageIcon()); |
| 172 | 172 | testImage(12, 9, "housenumber_small-AUTO-default", resource.getImageIcon(ImageResource.DEFAULT_DIMENSION)); |
| 173 | | testImage(8, 8, "housenumber_small-AUTO-08x08", resource.getImageIcon(new Dimension(8, 8))); |
| 174 | | testImage(16, 16, "housenumber_small-AUTO-16x16", resource.getImageIcon(new Dimension(16, 16))); |
| 175 | | testImage(24, 24, "housenumber_small-AUTO-24x24", resource.getImageIcon(new Dimension(24, 24))); |
| | 173 | testImage(8, 6, "housenumber_small-AUTO-08x08", resource.getImageIcon(new Dimension(8, 8))); |
| | 174 | testImage(16, 12, "housenumber_small-AUTO-16x16", resource.getImageIcon(new Dimension(16, 16))); |
| | 175 | testImage(24, 18, "housenumber_small-AUTO-24x24", resource.getImageIcon(new Dimension(24, 24))); |
| 176 | 176 | testImage(36, 27, "housenumber_small-AUTO-36x27", resource.getImageIcon(new Dimension(36, 27))); |
| 177 | 177 | } |
| 178 | 178 | |
| … |
… |
public void testImageIcon() throws IOException {
|
| 184 | 184 | public void testImageIconBounded() throws IOException { |
| 185 | 185 | ImageResource resource = new ImageProvider("presets/misc/housenumber_small").getResource(); |
| 186 | 186 | testImage(8, 6, "housenumber_small-BOUNDED-08x08", resource.getImageIconBounded(new Dimension(8, 8))); |
| 187 | | testImage(16, 12, "housenumber_small-BOUNDED-16x16", resource.getImageIconBounded(new Dimension(16, 16))); |
| 188 | | testImage(24, 18, "housenumber_small-BOUNDED-24x24", resource.getImageIconBounded(new Dimension(24, 24))); |
| | 187 | testImage(12, 9, "housenumber_small-BOUNDED-16x16", resource.getImageIconBounded(new Dimension(16, 16))); |
| | 188 | testImage(12, 9, "housenumber_small-BOUNDED-24x24", resource.getImageIconBounded(new Dimension(24, 24))); |
| 189 | 189 | } |
| 190 | 190 | |
| 191 | 191 | /** |
diff --git a/test/unit/org/openstreetmap/josm/tools/ImageResizeModeTest.java b/test/unit/org/openstreetmap/josm/tools/ImageResizeModeTest.java
index 2f014281c..9b606ce16 100644
|
a
|
b
|
public void testComputeDimensionAuto() {
|
| 39 | 39 | assertEquals(new Dimension(64, 48), ImageResizeMode.AUTO.computeDimension(new Dimension(64, 48), image)); |
| 40 | 40 | assertEquals(new Dimension(32, 24), ImageResizeMode.AUTO.computeDimension(new Dimension(32, -1), image)); |
| 41 | 41 | assertEquals(new Dimension(21, 16), ImageResizeMode.AUTO.computeDimension(new Dimension(-1, 16), image)); |
| 42 | | assertEquals(new Dimension(24, 32), ImageResizeMode.AUTO.computeDimension(new Dimension(24, 32), image)); |
| | 42 | assertEquals(new Dimension(24, 18), ImageResizeMode.AUTO.computeDimension(new Dimension(24, 32), image)); |
| 43 | 43 | } |
| 44 | 44 | |
| 45 | 45 | /** |