/******************************************************************************* * Copyright (c) MOBAC developers * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. ******************************************************************************/ package mobac.program.atlascreators; import java.awt.Point; import java.awt.geom.Point2D; import java.io.File; import java.io.IOException; import javax.imageio.ImageIO; import mobac.exceptions.AtlasTestException; import mobac.exceptions.MapCreationException; import mobac.mapsources.mapspace.MercatorPower2MapSpace; import mobac.program.annotations.AtlasCreatorName; import mobac.program.annotations.SupportedParameters; import mobac.program.atlascreators.impl.rmp.BoundingRect; import mobac.program.atlascreators.impl.rmp.MultiImage; import mobac.program.atlascreators.impl.rmp.RmpLayer; import mobac.program.atlascreators.impl.rmp.RmpLayer.TLMEntry; import mobac.program.atlascreators.impl.rmp.RmpTools; import mobac.program.atlascreators.impl.rmp.RmpWriter; import mobac.program.atlascreators.impl.rmp.Tiledata; import mobac.program.atlascreators.impl.rmp.rmpfile.Bmp2bit; import mobac.program.atlascreators.impl.rmp.rmpfile.Bmp4bit; import mobac.program.atlascreators.tileprovider.TileProvider; import mobac.program.interfaces.AtlasInterface; import mobac.program.interfaces.LayerInterface; import mobac.program.interfaces.MapInterface; import mobac.program.interfaces.MapSource; import mobac.program.interfaces.MapSpace; import mobac.program.interfaces.TileImageDataWriter; import mobac.program.model.TileImageParameters.Name; import mobac.program.tiledatawriter.TileImageJpegDataWriter; @AtlasCreatorName(value = "Magellan (RMP)", type = "Rmp") @SupportedParameters(names = { Name.format_jpg }) public class MagellanRmp extends AtlasCreator { TileImageDataWriter tileWriter = null; RmpWriter rmpWriter = null; String imageName = null; int layerNum = 0; @Override public boolean testMapSource(MapSource mapSource) { return MercatorPower2MapSpace.INSTANCE_256.equals(mapSource.getMapSpace()); } @Override public void startAtlasCreation(AtlasInterface atlas, File customAtlasDir) throws IOException, InterruptedException, AtlasTestException { super.startAtlasCreation(atlas, customAtlasDir); int mapCount = 0; for (LayerInterface layer : atlas) mapCount += layer.getMapCount(); imageName = RmpTools.buildImageName(atlas.getName()); rmpWriter = new RmpWriter(imageName, mapCount, new File(atlasDir, imageName + ".rmp")); } @Override protected void testAtlas() throws AtlasTestException { for (LayerInterface layer : atlas) { for (MapInterface map : layer) { Point max = map.getMaxTileCoordinate(); Point min = map.getMinTileCoordinate(); // if (max.x - min.x > 18000 || max.y - min.y > 18000) // throw new AtlasTestException("Map too large. Max size 18000x18000"); if (map.getParameters() != null) { if (!(map.getParameters().getFormat().getDataWriter() instanceof TileImageJpegDataWriter)) throw new AtlasTestException("Only JPEG formats are supported", map); } } } } @Override public void initializeMap(MapInterface map, TileProvider mapTileProvider) { super.initializeMap(map, mapTileProvider); if (parameters != null) { tileWriter = parameters.getFormat().getDataWriter(); } else tileWriter = new TileImageJpegDataWriter(0.9); tileWriter.initialize(); } @Override public void createMap() throws MapCreationException, InterruptedException { createTiles(); } protected void createTiles() throws InterruptedException, MapCreationException { atlasProgress.initMapCreation(1000); ImageIO.setUseCache(false); MultiImage layerImage = new MultiImage(mapSource, mapDlTileProvider, map); try { RmpLayer layer = createLayer(layerImage, layerNum); String layerName = RmpTools.buildTileName(imageName, layerNum); TLMEntry tlmEntry = layer.getTLMFile(layerName); rmpWriter.prepareFileEntry(tlmEntry); rmpWriter.writeFileEntry(layer.getA00File(layerName)); tlmEntry.updateContent(); rmpWriter.writePreparedFileEntry(tlmEntry); atlasProgress.setMapCreationProgress(1000); } catch (IOException e) { throw new MapCreationException(map, e); } layerNum++; } @Override public void finishAtlasCreation() throws IOException, InterruptedException { if (rmpWriter == null) return; // Creation already aborted try { rmpWriter.writeFileEntry(new Bmp2bit()); rmpWriter.writeFileEntry(new Bmp4bit()); rmpWriter.writeDirectory(); } finally { rmpWriter.close(); rmpWriter = null; } } @Override public void abortAtlasCreation() throws IOException { super.abortAtlasCreation(); rmpWriter.delete(); rmpWriter = null; } /** * Create a new instance of a TLM file and fill it with the data of a calibrated image * * @param si * image to get data from * @param layer * Layer number - for status output only * @return TLM instance * @throws InterruptedException * @throws MapCreationException * @throws IOException */ public RmpLayer createLayer(MultiImage si, int layer) throws InterruptedException, MapCreationException, IOException { int count = 0; /* --- Create instance --- */ RmpLayer rmpLayer = new RmpLayer(this); /* --- Get the coordinate space of the image --- */ MapSpace mapSpace = mapSource.getMapSpace(); //double north = mapSpace.cYToLat(map.getMinTileCoordinate().y, zoom); //double south = mapSpace.cYToLat(map.getMaxTileCoordinate().y, zoom); //double west = mapSpace.cXToLon(map.getMinTileCoordinate().x, zoom); //double east = mapSpace.cXToLon(map.getMaxTileCoordinate().x, zoom); Point2D.Double p1 = mapSpace.cXYToLonLat(map.getMinTileCoordinate().x, map.getMinTileCoordinate().y, zoom); Point2D.Double p2 = mapSpace.cXYToLonLat(map.getMaxTileCoordinate().x, map.getMaxTileCoordinate().y, zoom); double north = p1.y; double south = p2.y; double west = p1.x; double east = p2.x; BoundingRect rect = new BoundingRect(-north, -south, west, east); Point max = map.getMaxTileCoordinate(); Point min = map.getMinTileCoordinate(); int imageWidth = max.x - min.x; int imageHeight = max.y - min.y; /* --- Calculate tile dimensions --- */ double tile_width = (rect.getEast() - rect.getWest()) * 256 / imageWidth; double tile_height = (rect.getSouth() - rect.getNorth()) * 256 / imageHeight; /* --- Calculate the positions of the upper left tile --- */ int x_start = (int) Math.floor((rect.getWest() + 180) / tile_width); int y_start = (int) Math.floor((rect.getNorth() + 90) / tile_height); double x_end = (rect.getEast() + 180.0) / tile_width; double y_end = (rect.getSouth() + 90.0) / tile_height; /* * Create the tiles - process works column wise, starting on the top left corner of the destination area. */ for (int x = x_start; x < x_end; x++) { for (int y = y_start; y < y_end; y++) { count++; /* --- Create tile --- */ BoundingRect subrect = new BoundingRect(y * tile_height - 90, (y + 1) * tile_height - 90, x * tile_width - 180, (x + 1) * tile_width - 180); Tiledata td = new Tiledata(tileWriter); td.posx = x; td.posy = y; td.rect = subrect; td.si = si; rmpLayer.addPreparedImage(td); } } /* --- Build the TLM file --- */ rmpLayer.buildTLMFile(tile_width, tile_height, rect.getWest(), rect.getEast(), rect.getNorth(), rect.getSouth()); return rmpLayer; } }