1 | // License: GPL. For details, see LICENSE file.
|
---|
2 | package org.openstreetmap.josm.tools;
|
---|
3 |
|
---|
4 | import java.awt.Dimension;
|
---|
5 | import java.awt.Graphics2D;
|
---|
6 | import java.awt.Image;
|
---|
7 | import java.awt.RenderingHints;
|
---|
8 | import java.awt.image.BufferedImage;
|
---|
9 | import java.util.function.Consumer;
|
---|
10 |
|
---|
11 | /**
|
---|
12 | * Determines how the image is sized/resized in {@link ImageResource#getImageIcon(Dimension, boolean, ImageResizeMode)}.
|
---|
13 | */
|
---|
14 | enum ImageResizeMode {
|
---|
15 |
|
---|
16 | AUTO {
|
---|
17 | @Override
|
---|
18 | Dimension computeDimension(Dimension dim, Dimension icon) {
|
---|
19 | CheckParameterUtil.ensureThat((dim.width > 0 || dim.width == -1) && (dim.height > 0 || dim.height == -1),
|
---|
20 | () -> dim + " is invalid");
|
---|
21 | if (dim.width == -1 && dim.height == -1) {
|
---|
22 | return new Dimension(GuiSizesHelper.getSizeDpiAdjusted(icon.width), GuiSizesHelper.getSizeDpiAdjusted(icon.height));
|
---|
23 | } else if (dim.width == -1) {
|
---|
24 | return new Dimension(Math.max(1, icon.width * dim.height / icon.height), dim.height);
|
---|
25 | } else if (dim.height == -1) {
|
---|
26 | return new Dimension(dim.width, Math.max(1, icon.height * dim.width / icon.width));
|
---|
27 | } else {
|
---|
28 | return dim;
|
---|
29 | }
|
---|
30 | }
|
---|
31 | },
|
---|
32 |
|
---|
33 | 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 | @Override
|
---|
44 | Dimension computeDimension(Dimension dim, Dimension icon) {
|
---|
45 | CheckParameterUtil.ensureThat((dim.width > 0 || dim.width == -1) && (dim.height > 0 || dim.height == -1),
|
---|
46 | () -> 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);
|
---|
58 | }
|
---|
59 | },
|
---|
60 |
|
---|
61 | PADDED {
|
---|
62 | @Override
|
---|
63 | Dimension computeDimension(Dimension dim, Dimension icon) {
|
---|
64 | CheckParameterUtil.ensureThat(dim.width > 0 && dim.height > 0, () -> dim + " is invalid");
|
---|
65 | return dim;
|
---|
66 | }
|
---|
67 |
|
---|
68 | @Override
|
---|
69 | void prepareGraphics(Dimension icon, BufferedImage image, Graphics2D g) {
|
---|
70 | g.setClip(0, 0, image.getWidth(), image.getHeight());
|
---|
71 | final double scale = Math.min(image.getWidth() / icon.getWidth(), image.getHeight() / icon.getHeight());
|
---|
72 | g.translate((image.getWidth() - icon.getWidth() * scale) / 2, (image.getHeight() - icon.getHeight() * scale) / 2);
|
---|
73 | g.scale(scale, scale);
|
---|
74 | }
|
---|
75 | };
|
---|
76 |
|
---|
77 | /**
|
---|
78 | * Computes the dimension for the resulting image
|
---|
79 | * @param dim the desired image dimension
|
---|
80 | * @param icon the dimensions of the image to resize
|
---|
81 | * @return the dimension for the resulting image
|
---|
82 | */
|
---|
83 | abstract Dimension computeDimension(Dimension dim, Dimension icon);
|
---|
84 |
|
---|
85 | /**
|
---|
86 | * Creates a new buffered image and applies the rendering function
|
---|
87 | * @param dim the desired image dimension
|
---|
88 | * @param icon the dimensions of the image to resize
|
---|
89 | * @param renderer the rendering function
|
---|
90 | * @param sourceIcon the source icon to draw
|
---|
91 | * @return a new buffered image
|
---|
92 | * @throws IllegalArgumentException if renderer or sourceIcon is null
|
---|
93 | */
|
---|
94 | BufferedImage createBufferedImage(Dimension dim, Dimension icon, Consumer<Graphics2D> renderer, Image sourceIcon) {
|
---|
95 | final Dimension real = computeDimension(dim, icon);
|
---|
96 | final BufferedImage bufferedImage = new BufferedImage(real.width, real.height, BufferedImage.TYPE_INT_ARGB);
|
---|
97 | final Graphics2D g = bufferedImage.createGraphics();
|
---|
98 | g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
---|
99 | if (renderer != null) {
|
---|
100 | prepareGraphics(icon, bufferedImage, g);
|
---|
101 | renderer.accept(g);
|
---|
102 | } else if (sourceIcon != null) {
|
---|
103 | sourceIcon = sourceIcon.getScaledInstance(real.width, real.height, Image.SCALE_SMOOTH);
|
---|
104 | g.drawImage(sourceIcon, 0, 0, null);
|
---|
105 | } else {
|
---|
106 | throw new IllegalArgumentException("renderer or sourceIcon");
|
---|
107 | }
|
---|
108 | return bufferedImage;
|
---|
109 | }
|
---|
110 |
|
---|
111 | /**
|
---|
112 | * Prepares the graphics object for rendering the given image
|
---|
113 | * @param icon the dimensions of the image to resize
|
---|
114 | * @param image the image to render afterwards
|
---|
115 | * @param g graphics
|
---|
116 | */
|
---|
117 | void prepareGraphics(Dimension icon, BufferedImage image, Graphics2D g) {
|
---|
118 | g.setClip(0, 0, image.getWidth(), image.getHeight());
|
---|
119 | g.scale(image.getWidth() / icon.getWidth(), image.getHeight() / icon.getHeight());
|
---|
120 | }
|
---|
121 |
|
---|
122 | /**
|
---|
123 | * Returns a cache key for this mode and the given dimension
|
---|
124 | * @param dim the desired image dimension
|
---|
125 | * @return a cache key
|
---|
126 | */
|
---|
127 | int cacheKey(Dimension dim) {
|
---|
128 | return (ordinal() << 28) | ((dim.width & 0xfff) << 16) | (dim.height & 0xfff);
|
---|
129 | }
|
---|
130 |
|
---|
131 | }
|
---|