source: josm/trunk/test/functional/org/openstreetmap/josm/tools/ImageProviderTest.java@ 16983

Last change on this file since 16983 was 16983, checked in by simon04, 4 years ago

see #18694 - Extract ImageProviderTestManual, ImageProviderTestIT

  • Property svn:eol-style set to native
File size: 12.5 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.tools;
3
4import static java.awt.image.BufferedImage.TYPE_INT_ARGB;
5import static org.junit.Assert.assertEquals;
6import static org.junit.Assert.assertFalse;
7import static org.junit.Assert.assertNotNull;
8import static org.junit.Assert.assertTrue;
9import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
10import static org.openstreetmap.josm.gui.mappaint.MapCSSRendererTest.assertImageEquals;
11
12import java.awt.Dimension;
13import java.awt.GraphicsEnvironment;
14import java.awt.Image;
15import java.awt.Point;
16import java.awt.Toolkit;
17import java.awt.Transparency;
18import java.awt.image.BufferedImage;
19import java.io.File;
20import java.io.IOException;
21import java.util.Arrays;
22import java.util.Collections;
23import java.util.List;
24import java.util.logging.Handler;
25import java.util.logging.LogRecord;
26import java.util.logging.Logger;
27
28import javax.swing.ImageIcon;
29
30import org.junit.Before;
31import org.junit.BeforeClass;
32import org.junit.Rule;
33import org.junit.Test;
34import org.openstreetmap.josm.JOSMFixture;
35import org.openstreetmap.josm.TestUtils;
36import org.openstreetmap.josm.data.coor.LatLon;
37import org.openstreetmap.josm.data.osm.Node;
38import org.openstreetmap.josm.gui.tagging.presets.TaggingPreset;
39import org.openstreetmap.josm.gui.tagging.presets.TaggingPresets;
40import org.openstreetmap.josm.gui.tagging.presets.items.Key;
41import org.openstreetmap.josm.testutils.JOSMTestRules;
42import org.xml.sax.SAXException;
43
44import com.kitfox.svg.SVGConst;
45
46import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
47
48/**
49 * Unit tests of {@link ImageProvider} class.
50 */
51public class ImageProviderTest {
52
53 /**
54 * Setup test.
55 */
56 @Rule
57 @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
58 public JOSMTestRules test = new JOSMTestRules();
59
60 private static final class LogHandler14319 extends Handler {
61 boolean failed;
62
63 @Override
64 public void publish(LogRecord record) {
65 if ("Could not load image: https://host-in-the-trusted-network.com/test.jpg".equals(record.getMessage())) {
66 failed = true;
67 }
68 }
69
70 @Override
71 public void flush() {
72 }
73
74 @Override
75 public void close() throws SecurityException {
76 }
77 }
78
79 /**
80 * Setup test.
81 */
82 @BeforeClass
83 public static void setUp() {
84 JOSMFixture.createUnitTestFixture().init();
85 }
86
87 @Before
88 public void resetPixelDensity() {
89 GuiSizesHelper.setPixelDensity(1.0f);
90 }
91
92 /**
93 * Non-regression test for ticket <a href="https://josm.openstreetmap.de/ticket/9984">#9984</a>
94 * @throws IOException if an error occurs during reading
95 */
96 @Test
97 public void testTicket9984() throws IOException {
98 File file = new File(TestUtils.getRegressionDataFile(9984, "tile.png"));
99 assertEquals(Transparency.TRANSLUCENT, ImageProvider.read(file, true, true).getTransparency());
100 assertEquals(Transparency.TRANSLUCENT, ImageProvider.read(file, false, true).getTransparency());
101 long expectedTransparency = Utils.getJavaVersion() < 11 ? Transparency.OPAQUE : Transparency.TRANSLUCENT;
102 assertEquals(expectedTransparency, ImageProvider.read(file, false, false).getTransparency());
103 assertEquals(expectedTransparency, ImageProvider.read(file, true, false).getTransparency());
104 }
105
106 /**
107 * Non-regression test for ticket <a href="https://josm.openstreetmap.de/ticket/10030">#10030</a>
108 * @throws IOException if an error occurs during reading
109 */
110 @Test
111 public void testTicket10030() throws IOException {
112 File file = new File(TestUtils.getRegressionDataFile(10030, "tile.jpg"));
113 BufferedImage img = ImageProvider.read(file, true, true);
114 assertNotNull(img);
115 }
116
117 /**
118 * Non-regression test for ticket <a href="https://josm.openstreetmap.de/ticket/14319">#14319</a>
119 * @throws IOException if an error occurs during reading
120 */
121 @Test
122 @SuppressFBWarnings(value = "LG_LOST_LOGGER_DUE_TO_WEAK_REFERENCE")
123 public void testTicket14319() throws IOException {
124 LogHandler14319 handler = new LogHandler14319();
125 Logger.getLogger(SVGConst.SVG_LOGGER).addHandler(handler);
126 ImageIcon img = new ImageProvider(
127 new File(TestUtils.getRegressionDataDir(14319)).getAbsolutePath(), "attack.svg").get();
128 assertNotNull(img);
129 assertFalse(handler.failed);
130 }
131
132 /**
133 * Non-regression test for ticket <a href="https://josm.openstreetmap.de/ticket/19551">#19551</a>
134 * @throws SAXException If the type cannot be set (shouldn't throw)
135 */
136 @Test
137 public void testTicket19551() throws SAXException {
138 TaggingPreset badPreset = new TaggingPreset();
139 badPreset.setType("node,way,relation,closedway");
140 Key key = new Key();
141 key.key = "amenity";
142 key.value = "fuel";
143 badPreset.data.add(key);
144 TaggingPreset goodPreset = new TaggingPreset();
145 goodPreset.setType("node,way,relation,closedway");
146 goodPreset.data.add(key);
147 goodPreset.iconName = "stop";
148 TaggingPresets.addTaggingPresets(Arrays.asList(goodPreset, badPreset));
149 Node node = new Node(LatLon.ZERO);
150 node.put("amenity", "fuel");
151 assertDoesNotThrow(() -> OsmPrimitiveImageProvider.getResource(node, Collections.emptyList()));
152 }
153
154 /**
155 * Test fetching an image using {@code data:} URL.
156 */
157 @Test
158 public void testDataUrl() {
159 // Red dot image, taken from https://en.wikipedia.org/wiki/Data_URI_scheme#HTML
160 assertNotNull(ImageProvider.get("data:image/png;base64," +
161 "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4"+
162 "//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="));
163 }
164
165 /**
166 * Unit test of {@link ImageResource#getImageIcon(java.awt.Dimension)}
167 * @throws IOException if an I/O error occurs
168 */
169 @Test
170 public void testImageIcon() throws IOException {
171 ImageResource resource = new ImageProvider("presets/misc/housenumber_small").getResource();
172 testImage(12, 9, "housenumber_small-AUTO-null", resource.getImageIcon());
173 testImage(12, 9, "housenumber_small-AUTO-default", resource.getImageIcon(ImageResource.DEFAULT_DIMENSION));
174 testImage(8, 8, "housenumber_small-AUTO-08x08", resource.getImageIcon(new Dimension(8, 8)));
175 testImage(16, 16, "housenumber_small-AUTO-16x16", resource.getImageIcon(new Dimension(16, 16)));
176 testImage(24, 24, "housenumber_small-AUTO-24x24", resource.getImageIcon(new Dimension(24, 24)));
177 testImage(36, 27, "housenumber_small-AUTO-36x27", resource.getImageIcon(new Dimension(36, 27)));
178 }
179
180 /**
181 * Unit test of {@link ImageResource#getImageIconBounded(java.awt.Dimension)}
182 * @throws IOException if an I/O error occurs
183 */
184 @Test
185 public void testImageIconBounded() throws IOException {
186 ImageResource resource = new ImageProvider("presets/misc/housenumber_small").getResource();
187 testImage(8, 6, "housenumber_small-BOUNDED-08x08", resource.getImageIconBounded(new Dimension(8, 8)));
188 testImage(12, 9, "housenumber_small-BOUNDED-16x16", resource.getImageIconBounded(new Dimension(16, 16)));
189 testImage(12, 9, "housenumber_small-BOUNDED-24x24", resource.getImageIconBounded(new Dimension(24, 24)));
190 }
191
192 /**
193 * Unit test of {@link ImageResource#getPaddedIcon(java.awt.Dimension)}
194 * @throws IOException if an I/O error occurs
195 */
196 @Test
197 public void testImageIconPadded() throws IOException {
198 ImageResource resource = new ImageProvider("presets/misc/housenumber_small").getResource();
199 testImage(8, 8, "housenumber_small-PADDED-08x08", resource.getPaddedIcon(new Dimension(8, 8)));
200 testImage(16, 16, "housenumber_small-PADDED-16x16", resource.getPaddedIcon(new Dimension(16, 16)));
201 testImage(24, 24, "housenumber_small-PADDED-24x24", resource.getPaddedIcon(new Dimension(24, 24)));
202 }
203
204 private static void testImage(int width, int height, String reference, ImageIcon icon) throws IOException {
205 final BufferedImage image = (BufferedImage) icon.getImage();
206 final File referenceFile = new File(
207 TestUtils.getTestDataRoot() + "/" + ImageProviderTest.class.getSimpleName() + "/" + reference + ".png");
208 assertEquals("width", width, image.getWidth(null));
209 assertEquals("height", height, image.getHeight(null));
210 assertImageEquals(reference, referenceFile, image, 0, 0, null);
211 }
212
213 /**
214 * Test getting a bounded icon given some UI scaling configured.
215 */
216 @Test
217 public void testGetImageIconBounded() {
218 int scale = 2;
219 GuiSizesHelper.setPixelDensity(scale);
220
221 ImageProvider imageProvider = new ImageProvider("open").setOptional(true);
222 ImageResource resource = imageProvider.getResource();
223 Dimension iconDimension = ImageProvider.ImageSizes.SMALLICON.getImageDimension();
224 ImageIcon icon = resource.getImageIconBounded(iconDimension);
225 Image image = icon.getImage();
226 List<Image> resolutionVariants = HiDPISupport.getResolutionVariants(image);
227 if (resolutionVariants.size() > 1) {
228 assertEquals(2, resolutionVariants.size());
229 int expectedVirtualWidth = ImageProvider.ImageSizes.SMALLICON.getVirtualWidth();
230 assertEquals(expectedVirtualWidth * scale, resolutionVariants.get(0).getWidth(null));
231 assertEquals((int) Math.round(expectedVirtualWidth * scale * HiDPISupport.getHiDPIScale()),
232 resolutionVariants.get(1).getWidth(null));
233 }
234 }
235
236 /**
237 * Test getting an image for a crosshair cursor.
238 */
239 @Test
240 public void testGetCursorImageForCrosshair() {
241 if (GraphicsEnvironment.isHeadless()) {
242 // TODO mock Toolkit.getDefaultToolkit().getBestCursorSize()
243 return;
244 }
245 Point hotSpot = new Point();
246 Image image = ImageProvider.getCursorImage("crosshair", null, hotSpot);
247 assertCursorDimensionsCorrect(new Point.Double(10.0, 10.0), image, hotSpot);
248 }
249
250 /**
251 * Test getting an image for a custom cursor with overlay.
252 */
253 @Test
254 public void testGetCursorImageWithOverlay() {
255 testCursorImageWithOverlay(1.0f); // normal case
256 testCursorImageWithOverlay(1.5f); // user has configured a GUI scale of 1.5 in the JOSM advanced preferences
257 }
258
259 private void testCursorImageWithOverlay(float guiScale) {
260 if (GraphicsEnvironment.isHeadless()) {
261 // TODO mock Toolkit.getDefaultToolkit().getBestCursorSize()
262 return;
263 }
264 GuiSizesHelper.setPixelDensity(guiScale);
265 Point hotSpot = new Point();
266 Image image = ImageProvider.getCursorImage("normal", "selection", hotSpot);
267 assertCursorDimensionsCorrect(new Point.Double(3.0, 2.0), image, hotSpot);
268 BufferedImage bufferedImage = new BufferedImage(image.getWidth(null), image.getWidth(null), TYPE_INT_ARGB);
269 bufferedImage.getGraphics().drawImage(image, 0, 0, null);
270
271 // check that the square of 1/4 size right lower to the center has some non-empty pixels
272 boolean nonEmptyPixelExistsRightLowerToCenter = false;
273 for (int x = image.getWidth(null) / 2; x < image.getWidth(null) * 3 / 4; ++x) {
274 for (int y = image.getHeight(null) / 2; y < image.getWidth(null) * 3 / 4; ++y) {
275 if (bufferedImage.getRGB(x, y) != 0)
276 nonEmptyPixelExistsRightLowerToCenter = true;
277 }
278 }
279 assertTrue(nonEmptyPixelExistsRightLowerToCenter);
280 }
281
282 private void assertCursorDimensionsCorrect(Point.Double originalHotspot, Image image, Point hotSpot) {
283 int originalCursorSize = ImageProvider.CURSOR_SIZE_HOTSPOT_IS_RELATIVE_TO;
284 Dimension bestCursorSize = Toolkit.getDefaultToolkit().getBestCursorSize(originalCursorSize, originalCursorSize);
285 Image bestCursorImage = HiDPISupport.getResolutionVariant(image, bestCursorSize.width, bestCursorSize.height);
286 int bestCursorImageWidth = bestCursorImage.getWidth(null);
287 assertEquals((int) Math.round(bestCursorSize.getWidth()), bestCursorImageWidth);
288 int bestCursorImageHeight = bestCursorImage.getHeight(null);
289 assertEquals((int) Math.round(bestCursorSize.getHeight()), bestCursorImageHeight);
290 assertEquals(originalHotspot.x / originalCursorSize * bestCursorImageWidth, hotSpot.x, 1 /* at worst one pixel off */);
291 assertEquals(originalHotspot.y / originalCursorSize * bestCursorImageHeight, hotSpot.y, 1 /* at worst one pixel off */);
292 }
293
294}
Note: See TracBrowser for help on using the repository browser.