package org.geotools.renderer.lite; import java.awt.Color; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.awt.image.BufferedImage; import java.util.HashMap; import java.util.Map; import java.util.concurrent.CountDownLatch; import javax.swing.SwingUtilities; import org.geotools.geometry.jts.ReferencedEnvelope; import org.geotools.map.DirectLayer; import org.geotools.map.MapContent; import org.geotools.map.MapViewport; import org.geotools.referencing.crs.DefaultGeographicCRS; import org.geotools.test.TestData; import org.jaitools.swing.ImageFrame; import org.junit.Test; import static org.junit.Assert.*; /** * @author michael * * @source $URL$ */ public class StreamingRendererDirectLayerTest { private static final ReferencedEnvelope WORLD = new ReferencedEnvelope(0, 1, 0, 1, DefaultGeographicCRS.WGS84); private static final Rectangle SCREEN = new Rectangle(200, 200); private class MockLayer extends DirectLayer { /* * Just draws a rectangle using graphics coordinates. * * TODO: Replace this with something using world coordinates * and the world to screen transform. */ @Override public void draw(Graphics2D graphics, MapContent map, MapViewport viewport) { Graphics2D localGraphics = (Graphics2D) graphics.create(); localGraphics.setPaint(Color.WHITE); localGraphics.fill(SCREEN); Rectangle inner = new Rectangle( SCREEN.x + SCREEN.width / 4, SCREEN.y + SCREEN.height / 4, SCREEN.width / 2, SCREEN.height / 2); localGraphics.setPaint(Color.BLACK); localGraphics.fill(inner); } @Override public ReferencedEnvelope getBounds() { return WORLD; } } @Test public void rendererRecognizesDirectLayer() { MapContent mapContent = new MapContent(); mapContent.addLayer( new MockLayer() ); StreamingRenderer renderer = new StreamingRenderer(); renderer.setMapContent(mapContent); BufferedImage image = new BufferedImage(SCREEN.width, SCREEN.height, BufferedImage.TYPE_INT_ARGB); mapContent.getViewport().setScreenArea(SCREEN); Graphics2D destGraphics = image.createGraphics(); renderer.paint(destGraphics, SCREEN, WORLD); // PerceptualDiff could be used to examine the resulting image. // For now we just do a quick and dirty check Map<Integer, Integer> colorFreq = getColorFreq(image); assertEquals(2, colorFreq.size()); assertTrue(colorFreq.containsKey(Color.BLACK.getRGB())); assertTrue(colorFreq.containsKey(Color.WHITE.getRGB())); double ratio = (double) colorFreq.get(Color.BLACK.getRGB()) / colorFreq.get(Color.WHITE.getRGB()); assertTrue(ratio > 0.95 && ratio < 1.05); if (TestData.isInteractiveTest()) { CountDownLatch latch = new CountDownLatch(1); displayImage(image, latch); try { latch.await(); } catch (InterruptedException ex) { throw new RuntimeException(ex); } } } /* * TODO: replace this with a PerceptualDiff check or something */ private Map<Integer, Integer> getColorFreq(BufferedImage image) { Map<Integer, Integer> colorFreq = new HashMap<Integer, Integer>(); for (int y = image.getMinY(), ny = 0; ny < image.getHeight(); y++, ny++) { for (int x = image.getMinX(), nx = 0; nx < image.getWidth(); x++, nx++) { int rgb = image.getRGB(x, y); Integer freq = colorFreq.get(rgb); if (freq == null) { colorFreq.put(rgb, 1); } else { freq++ ; } } } return colorFreq; } private void displayImage(final BufferedImage image, final CountDownLatch latch) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { TestImageFrame frame = new TestImageFrame(image, latch); frame.setVisible(true); } }); } private static class TestImageFrame extends ImageFrame { BufferedImage image; public TestImageFrame(final BufferedImage image, final CountDownLatch latch) { super(image, "Rendered image"); setDefaultCloseOperation(DISPOSE_ON_CLOSE); addWindowListener(new WindowAdapter() { @Override public void windowClosed(WindowEvent e) { latch.countDown(); } }); setSize(image.getWidth(), image.getHeight() + 21); } } }