package tools.image; import java.awt.AlphaComposite; import java.awt.Composite; import java.awt.Graphics2D; import java.awt.GraphicsConfiguration; import java.awt.GraphicsEnvironment; import java.awt.Image; import java.awt.MediaTracker; import java.awt.Panel; import java.awt.Polygon; import java.awt.Rectangle; import java.awt.Toolkit; import java.awt.Transparency; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.util.Iterator; import javax.imageio.ImageIO; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import games.strategy.debug.ClientLogger; import games.strategy.triplea.ui.mapdata.MapData; import games.strategy.ui.Util; import tools.map.making.ImageIoCompletionWatcher; /** * Utility for breaking an image into seperate smaller images. * User must make a new directory called "newImages" and then run the utility * first. * To create sea zones only, he must choose "Y" at the prompt. To create * territories, he must choose "N" at the prompt. * sea zone images directory must be renamed to "seazone */ public class ReliefImageBreaker { private static String location = null; private static JFrame observer = new JFrame(); private boolean seaZoneOnly; private MapData mapData; private static File s_mapFolderLocation = null; private static final String TRIPLEA_MAP_FOLDER = "triplea.map.folder"; /** * Creates a new instance of ReliefImageBreaker and calls createMaps() method to start the computations. */ public static void main(final String[] args) throws Exception { handleCommandLineArgs(args); JOptionPane.showMessageDialog(null, new JLabel("<html>" + "This is the ReliefImageBreaker, it is no longer used. " + "<br>It will take any image and finalized map folder, and will create cut out images of the relief art " + "<br>for each territory and sea zone." + "<br><br>TripleA no longer uses these, and instead uses reliefTiles (use the TileImageBreaker for that)." + "</html>")); final FileSave locationSelection = new FileSave("Where to save Relief Images?", null, s_mapFolderLocation); location = locationSelection.getPathString(); if (s_mapFolderLocation == null && locationSelection.getFile() != null) { s_mapFolderLocation = locationSelection.getFile().getParentFile(); } if (location == null) { System.out.println("You need to select a folder to save the tiles in for this to work"); System.out.println("Shutting down"); System.exit(0); return; } new ReliefImageBreaker().createMaps(); } /** * One of the main methods that is used to create the actual maps. Calls on * various methods to get user input and create the maps. */ public void createMaps() throws IOException { // ask user to input image location final Image map = loadImage(); if (map == null) { System.out.println("You need to select a map image for this to work"); System.out.println("Shutting down"); System.exit(0); } // ask user wether it is sea zone only or not seaZoneOnly = doSeaZone(); // ask user where the map is final String mapDir = getMapDirectory(); if (mapDir == null || mapDir.equals("")) { System.out.println("You need to specify a map name for this to work"); System.out.println("Shutting down"); System.exit(0); } try { mapData = new MapData(mapDir); // files for the map. } catch (final NullPointerException npe) { System.out.println("Bad data given or missing text files, shutting down"); System.exit(0); } for (final String territoryName : mapData.getTerritories()) { final boolean seaZone = Util.isTerritoryNameIndicatingWater(territoryName); if (!seaZone && seaZoneOnly) { continue; } if (seaZone && !seaZoneOnly) { continue; } processImage(territoryName, map); } System.out.println("All Finished!"); System.exit(0); } /** * Asks user wether to do sea zones only or not * * @return java.lang.boolean TRUE to do seazones only. */ private static boolean doSeaZone() { String ans = ""; while (true) { ans = JOptionPane.showInputDialog(null, "Only Do Sea Zones? Enter [Y/N]"); if (ans == null) { System.out.println("Cannot leave this blank!"); System.out.println("Retry"); } else { if (ans.equalsIgnoreCase("Y")) { return true; } else if (ans.equalsIgnoreCase("N")) { return false; } else { System.out.println("You must enter Y or N"); } } } } /** * Asks the user to input a valid map name that will be used to form the map * directory in the core of TripleA in the class TerritoryData. * we need the exact map name as indicated in the XML game file ie."revised" * "classic" "pact_of_steel" of course, without the quotes. * * @return map name entered by the user (if any, null returned if canceled) */ private static String getMapDirectory() { final String mapDir = JOptionPane.showInputDialog(null, "Enter the name of the map (ie. revised)"); if (mapDir != null) { return mapDir; } else { return null; } } /** * Asks the user to select an image and then it loads it up into an Image * object and returns it to the calling class. * * @return java.awt.Image img the loaded image */ private static Image loadImage() { System.out.println("Select the map"); final String mapName = new FileOpen("Select The Map", s_mapFolderLocation, ".gif", ".png").getPathString(); if (mapName != null) { final Image img = Toolkit.getDefaultToolkit().createImage(mapName); final MediaTracker tracker = new MediaTracker(new Panel()); tracker.addImage(img, 1); try { tracker.waitForAll(); return img; } catch (final InterruptedException e) { ClientLogger.logQuietly("interrupted while loading images", e); return loadImage(); } } else { return null; } } private void processImage(final String territory, final Image map) throws IOException { final Rectangle bounds = mapData.getBoundingRect(territory); final int width = bounds.width; final int height = bounds.height; final BufferedImage alphaChannelImage = Util.createImage(bounds.width, bounds.height, true); final Iterator<Polygon> iter = mapData.getPolygons(territory).iterator(); while (iter.hasNext()) { Polygon item = iter.next(); item = new Polygon(item.xpoints, item.ypoints, item.npoints); item.translate(-bounds.x, -bounds.y); alphaChannelImage.getGraphics().fillPolygon(item); } final GraphicsConfiguration m_localGraphicSystem = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration(); final BufferedImage relief = m_localGraphicSystem.createCompatibleImage(width, height, seaZoneOnly ? Transparency.BITMASK : Transparency.TRANSLUCENT); relief.getGraphics().drawImage(map, 0, 0, width, height, bounds.x, bounds.y, bounds.x + width, bounds.y + height, observer); blankOutline(alphaChannelImage, relief); String outFileName = location + File.separator + territory; if (!seaZoneOnly) { outFileName += "_relief.png"; } else { outFileName += ".png"; } ImageIO.write(relief, "png", new File(outFileName)); System.out.println("wrote " + outFileName); } /** * Sets the alpha channel to the same as that of the base image. */ private static void blankOutline(final Image alphaChannelImage, final BufferedImage relief) { final Graphics2D gc = (Graphics2D) relief.getGraphics(); final Composite prevComposite = gc.getComposite(); gc.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_IN)); /* * draw the image, and check for the possibility it doesn't complete now */ final ImageIoCompletionWatcher watcher = new ImageIoCompletionWatcher(); final boolean drawComplete = gc.drawImage(alphaChannelImage, 0, 0, watcher); // use the watcher to for the draw to finish if (!drawComplete) { watcher.waitForCompletion(); } // cleanup gc.setComposite(prevComposite); } private static String getValue(final String arg) { final int index = arg.indexOf('='); if (index == -1) { return ""; } return arg.substring(index + 1); } private static void handleCommandLineArgs(final String[] args) { // arg can only be the map folder location. if (args.length == 1) { String value; if (args[0].startsWith(TRIPLEA_MAP_FOLDER)) { value = getValue(args[0]); } else { value = args[0]; } final File mapFolder = new File(value); if (mapFolder.exists()) { s_mapFolderLocation = mapFolder; } else { System.out.println("Could not find directory: " + value); } } else if (args.length > 1) { System.out.println("Only argument allowed is the map directory."); } // might be set by -D if (s_mapFolderLocation == null || s_mapFolderLocation.length() < 1) { final String value = System.getProperty(TRIPLEA_MAP_FOLDER); if (value != null && value.length() > 0) { final File mapFolder = new File(value); if (mapFolder.exists()) { s_mapFolderLocation = mapFolder; } else { System.out.println("Could not find directory: " + value); } } } } }