package org.geowebcache.layer.wms; import java.awt.Graphics2D; import java.awt.Color; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import java.awt.image.RenderedImage; import java.util.Arrays; import java.util.Collections; import java.util.Hashtable; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Random; import junit.framework.TestCase; import org.geowebcache.grid.BoundingBox; import org.geowebcache.grid.GridSetBroker; import org.geowebcache.grid.GridSubset; import org.geowebcache.grid.GridSubsetFactory; import org.geowebcache.layer.MetaTile; import org.geowebcache.mime.ApplicationMime; import org.geowebcache.mime.ImageMime; import javax.media.jai.PlanarImage; public class MetaTileTest extends TestCase { GridSetBroker gridSetBroker = new GridSetBroker(false, false); @Override protected void setUp() throws Exception { super.setUp(); } public void test1MetaTile() throws Exception { BoundingBox bbox = new BoundingBox(0, 0, 180, 90); int metaHeight = 1; int metaWidth = 1; GridSubset grid = GridSubsetFactory.createGridSubSet( gridSetBroker.WORLD_EPSG4326, bbox, 0, 30); long[] gridPos = { 0, 0, 0 }; //int[] gridBounds, int[] tileGridPosition, int metaX, int metaY WMSMetaTile mt = new WMSMetaTile( null, grid, ImageMime.png, null, gridPos, metaWidth, metaHeight, Collections.singletonMap("test", "test1")); long[] solution = { 0, 0, 0, 0, 0 }; boolean test = Arrays.equals(mt.getMetaTileGridBounds(), solution); if (!test) { System.out.println("1 - " + mt.debugString()); System.out.println("test1MetaTile {" + Arrays.toString(solution) + "} {" + Arrays.toString(mt.getMetaTileGridBounds()) + "}"); } assertTrue(test); } public void test2MetaTile() throws Exception { BoundingBox bbox = new BoundingBox(0, 0, 180, 90); int metaHeight = 3; int metaWidth = 3; GridSubset grid = GridSubsetFactory.createGridSubSet( gridSetBroker.WORLD_EPSG4326, bbox, 0, 30); long[] gridPos = { 127, 63, 6 }; WMSMetaTile mt = new WMSMetaTile( null, grid, ImageMime.png, null, gridPos, metaWidth, metaHeight, Collections.singletonMap("test", "test1")); long[] solution = { 126, 63, 127, 63, 6 }; boolean test = Arrays.equals(mt.getMetaTileGridBounds(), solution); if (!test) { System.out.println("2 - " + mt.debugString()); System.out.println("test2MetaTile {" + Arrays.toString(solution) + "} {" + Arrays.toString(mt.getMetaTileGridBounds()) + "}"); } assertTrue(test); } public void test3MetaTile() throws Exception { BoundingBox bbox = new BoundingBox(0, 0, 20037508.34, 20037508.34); int metaHeight = 1; int metaWidth = 1; GridSubset grid = GridSubsetFactory.createGridSubSet( gridSetBroker.WORLD_EPSG3857, bbox, 0, 30); long[] gridPos = { 0, 0, 0 }; WMSMetaTile mt = new WMSMetaTile( null, grid, ImageMime.png, null, gridPos, metaWidth, metaHeight, Collections.singletonMap("test", "test1")); long[] solution = { 0, 0, 0, 0, 0 }; boolean test = Arrays.equals(mt.getMetaTileGridBounds(), solution); if (!test) { System.out.println("3 - " + mt.debugString()); System.out.println("test3MetaTile {" + Arrays.toString(solution) + "} {" + Arrays.toString(mt.getMetaTileGridBounds()) + "}"); } assertTrue(test); } public void test4MetaTile() throws Exception { BoundingBox bbox = new BoundingBox(0, 0, 20037508.34, 20037508.34); int metaHeight = 3; int metaWidth = 3; GridSubset grid = GridSubsetFactory.createGridSubSet( gridSetBroker.WORLD_EPSG3857, bbox, 0, 30); long[] gridPos = { 70, 70, 6 }; WMSMetaTile mt = new WMSMetaTile( null, grid, ImageMime.png, null, gridPos, metaWidth, metaHeight, Collections.singletonMap("test", "test1")); long[] solution = { 69, 69, 63, 63, 6 }; boolean test = Arrays.equals(mt.getMetaTileGridBounds(), solution); if (test) { } else { System.out.println("4 - " + mt.debugString()); System.out.println("test4MetaTile {" + Arrays.toString(solution) + "} {" + Arrays.toString(mt.getMetaTileGridBounds()) + "}"); } assertTrue(test); } /** * * @throws Exception */ public void test5MetaTileGutter() throws Exception { BoundingBox bbox = new BoundingBox(0, 0, 180, 90); WMSLayer layer = createWMSLayer(bbox); GridSubset grid = GridSubsetFactory.createGridSubSet( gridSetBroker.WORLD_EPSG4326, bbox, 0, 30); // Set the gutter layer.gutter = 50; // Lets make a tile close to the edge, this should only have a gutter to west / south long[] gridPos = { 127, 63, 6 }; WMSMetaTile mt = new WMSMetaTile( layer, grid, ImageMime.png, null, gridPos, layer.getMetaTilingFactors()[0], layer.getMetaTilingFactors()[1], Collections.singletonMap("test", "test1")); // The actual gutter is calculated right at construction time Map<String, String> wmsParams = mt.getWMSParams(); assertEquals(layer.gutter.intValue(), mt.getGutter()[0]); assertEquals(layer.gutter.intValue(), mt.getGutter()[1]); assertEquals(0, mt.getGutter()[2]); assertEquals(0, mt.getGutter()[3]); int height = Integer.parseInt(wmsParams.get("HEIGHT")); assertEquals(height, 256 + 50); long[] midGridPos = { 83, 45, 6 }; mt = new WMSMetaTile( layer, grid, ImageMime.png, null, midGridPos, layer.getMetaTilingFactors()[0], layer.getMetaTilingFactors()[1], Collections.singletonMap("test", "test1")); // The actual gutter is calculated right at construction time wmsParams = mt.getWMSParams(); assertTrue(mt.getGutter()[0] == layer.gutter); assertTrue(mt.getGutter()[1] == layer.gutter); assertTrue(mt.getGutter()[2] == layer.gutter); assertTrue(mt.getGutter()[3] == layer.gutter); height = Integer.parseInt(wmsParams.get("HEIGHT")); assertEquals(height, 768 + 2*50); String[] coordStrs = wmsParams.get("BBOX").split(","); // Lets check some specific coordinates too assertTrue(Math.abs( Double.parseDouble(coordStrs[0]) - 47.26318359375) < 0.001); assertTrue(Math.abs( Double.parseDouble(coordStrs[3]) - 45.54931640625) < 0.001); } /** * * @throws Exception */ public void test6MetaTileNoGutterWithVector() throws Exception { BoundingBox bbox = new BoundingBox(0, 0, 180, 90); WMSLayer layer = createWMSLayer(bbox); GridSubset grid = GridSubsetFactory.createGridSubSet( gridSetBroker.WORLD_EPSG4326, bbox, 0, 30); // Set the gutter layer.gutter = 50; // Lets make a tile close to the edge, this should only have a gutter to west / south long[] gridPos = { 127, 63, 6 }; WMSMetaTile mt = new WMSMetaTile( layer, grid, ApplicationMime.topojson, null, gridPos, layer.getMetaTilingFactors()[0], layer.getMetaTilingFactors()[1], Collections.singletonMap("test", "test1")); // The actual gutter is calculated right at construction time Map<String, String> wmsParams = mt.getWMSParams(); assertEquals(0, mt.getGutter()[0]); assertEquals(0, mt.getGutter()[1]); assertEquals(0, mt.getGutter()[2]); assertEquals(0, mt.getGutter()[3]); int height = Integer.parseInt(wmsParams.get("HEIGHT")); assertEquals(height, 256); } private WMSLayer createWMSLayer(BoundingBox layerBounds) { String[] urls = {"http://localhost:38080/wms"}; List<String> formatList = new LinkedList<String>(); formatList.add("image/png"); Hashtable<String,GridSubset> grids = new Hashtable<String,GridSubset>(); GridSubset grid = GridSubsetFactory.createGridSubSet(gridSetBroker.WORLD_EPSG4326); grids.put(grid.getName(), grid); int[] metaWidthHeight = {3,3}; WMSLayer layer = new WMSLayer("test:layer", urls, "aStyle", "test:layer", formatList, grids, null, metaWidthHeight, "vendorparam=true", false, null); layer.initialize(gridSetBroker); return layer; } // Testing the create tile operation with a meta tile buffer image public void testCreateTileFromMetaTileBufferImage() throws Exception { // creating the meta tile image Color[][] colors = new Color[2][2]; BufferedImage image = createBufferImageMetaTile(2, 2, 256, 512, colors); // testing the tiles extraction as a buffer image commonCreateTileFromMetaTileTest(colors, image); } // Testing the create tile operation with a meta tile planar image public void testCreateTileFromMetaTilePlanarImage() throws Exception { // creating the meta tile image Color[][] colors = new Color[2][2]; BufferedImage image = createBufferImageMetaTile(2, 2, 256, 512, colors); // testing the tiles extraction as a planar image commonCreateTileFromMetaTileTest(colors, PlanarImage.wrapRenderedImage(image)); } // Helper class that given a meta tile image will extract the tiles and check that extracted tiles are correct private void commonCreateTileFromMetaTileTest(Color[][] colors, RenderedImage metaTileImage) throws Exception { // creating the meta tile BoundingBox boundingBox = new BoundingBox(0, 0, 180, 90); int metaHeight = 2; int metaWidth = 2; GridSubset grid = GridSubsetFactory.createGridSubSet(gridSetBroker.WORLD_EPSG4326, boundingBox, 0, 21); long[] gridPos = {0, 0, 0}; MetaTile metaTile = new MetaTile(grid, ImageMime.png, null, gridPos, metaWidth, metaHeight, null); metaTile.setImage(metaTileImage); // extracting the tiles using the create tile method int width = metaTile.getMetaTileWidth(); int height = metaTile.getMetaTileHeight(); checkImageBorderSameColor(metaTile.createTile(0, 0, width, height), colors[0][0]); checkImageBorderSameColor(metaTile.createTile(width, 0, width, height), colors[0][1]); checkImageBorderSameColor(metaTile.createTile(0, height, width, height), colors[1][0]); checkImageBorderSameColor(metaTile.createTile(width, height, width, height), colors[1][1]); } // Helper method that given an image and a color will check that the borders of the image are of the same color private void checkImageBorderSameColor(RenderedImage image, Color color) throws Exception { if (image instanceof PlanarImage) { image = ((PlanarImage) image).getAsBufferedImage(); } // extracting the borders pixels int width = image.getWidth(); int height = image.getHeight(); int[] borderA = (int[]) image.getData().getDataElements(0, 0, width, 1, null); int[] borderB = (int[]) image.getData().getDataElements(0, height - 1, width, 1, null); int[] borderC = (int[]) image.getData().getDataElements(0, 0, 1, height, null); int[] borderD = (int[]) image.getData().getDataElements(width - 1, 0, 1, height, null); int colorInt = color.getRGB(); // comparing the borders pixels with the expected color for (int i = 0; i < width; i++) { if (borderA[i] != colorInt || borderB[i] != colorInt) { fail("Not the expected color."); } } for (int i = 0; i < height; i++) { if (borderC[i] != colorInt || borderD[i] != colorInt) { fail("Not the expected color."); } } } // Helper method that creates a random image with random colors private BufferedImage createBufferImageMetaTile(int rows, int columns, int height, int width, Color[][] colors) { Random random = new Random(); BufferedImage image = new BufferedImage(columns * width, rows * height, BufferedImage.TYPE_INT_ARGB); Graphics2D graphics = image.createGraphics(); for (int i = 0; i < rows; i++) { for (int j = 0; j < columns; j++) { Color color = new Color(random.nextInt(256), random.nextInt(256), random.nextInt(256)); colors[i][j] = color; graphics.setColor(color); int x = j * width; int y = i * height; graphics.fill(new Rectangle2D.Float(x, y, width, height)); } } graphics.dispose(); return image; } }