package micropolisj.build_tool; import micropolisj.engine.TileSpec; import java.awt.*; import java.awt.image.BufferedImage; import java.io.*; import java.nio.charset.Charset; import java.util.*; import javax.imageio.*; import javax.swing.ImageIcon; public class MakeTiles { static HashMap tileData = new HashMap(); static HashMap loadedImages = new HashMap(); static final Charset UTF8 = Charset.forName("UTF-8"); static final int NTILES = 960; static int TILE_SIZE = 16; public static void main(String [] args) throws Exception { if (args.length != 2) { throw new Exception("Wrong number of arguments"); } if (System.getProperty("tile_size") != null) { TILE_SIZE = Integer.parseInt(System.getProperty("tile_size")); } File recipeFile = new File(args[0]); File outputFile = new File(args[1]); Properties recipe = new Properties(); recipe.load( new InputStreamReader( new FileInputStream(recipeFile), UTF8 )); // actually assemble the image BufferedImage buf = new BufferedImage(TILE_SIZE,TILE_SIZE*NTILES,BufferedImage.TYPE_INT_RGB); Graphics2D gr = buf.createGraphics(); for (int i = 0; i < NTILES; i++) { String rawSpec = recipe.getProperty(Integer.toString(i)); assert rawSpec != null; TileSpec tileSpec = TileSpec.parse(i, rawSpec); FrameSpec ref = parseFrameSpec(tileSpec); drawTo(ref, gr, 0, TILE_SIZE*i); } System.out.println("Generating tiles array: "+outputFile); ImageIO.write(buf, "png", outputFile); } static void drawTo(FrameSpec ref, Graphics2D gr, int destX, int destY) throws IOException { if (ref.background != null) { drawTo(ref.background, gr, destX, destY); } if (!loadedImages.containsKey(ref.fileName)) { loadedImages.put(ref.fileName, loadImage(ref.fileName)); } SourceImage sourceImg = loadedImages.get(ref.fileName); gr.drawImage( sourceImg.image, destX, destY, destX+TILE_SIZE, destY+TILE_SIZE, ref.offsetX * sourceImg.basisSize / 16, ref.offsetY * sourceImg.basisSize / 16, (ref.offsetX + (ref.width != 0 ? ref.width : 16)) * sourceImg.basisSize / 16, (ref.offsetY + (ref.height != 0 ? ref.height : 16)) * sourceImg.basisSize / 16, null); } static class SourceImage { Image image; int basisSize; SourceImage(Image image, int basisSize) { this.image = image; this.basisSize = basisSize; } } static class FrameSpec { FrameSpec background; String fileName; int offsetX; int offsetY; int width; int height; } static FrameSpec parseFrameSpec(TileSpec spec) { FrameSpec result = null; for (String layerStr : spec.getImages()) { FrameSpec rv = new FrameSpec(); rv.background = result; result = rv; String [] parts = layerStr.split("@", 2); rv.fileName = parts[0]; if (parts.length >= 2) { String offsetInfo = parts[1]; parts = offsetInfo.split(","); if (parts.length >= 1) { rv.offsetX = Integer.parseInt(parts[0]); } if (parts.length >= 2) { rv.offsetY = Integer.parseInt(parts[1]); } if (parts.length >= 3) { rv.width = Integer.parseInt(parts[2]); } if (parts.length >= 4) { rv.height = Integer.parseInt(parts[3]); } }//endif something given after '@' in image specifier }//end foreach layer in image specification return result; } static File findInkscape() { String exeName = "inkscape"; if (System.getProperty("os.name").startsWith("Windows")) { exeName += ".exe"; } File [] pathsToTry = { new File("/usr/bin"), new File("c:\\Program Files\\Inkscape"), new File("c:\\Program Files (x86)\\Inkscape") }; for (File p : pathsToTry) { File f = new File(p, exeName); if (f.exists()) { return f; } } throw new Error("INKSCAPE not installed (or not found)"); } static void renderSvg(File svgFile, File pngFile) throws IOException { if (pngFile.exists() && pngFile.lastModified() > svgFile.lastModified()) { // looks like the PNG file is already up-to-date return; } File inkscapeBin = findInkscape(); System.out.println("Generating raster image: "+pngFile); if (pngFile.exists()) { pngFile.delete(); } String [] cmdline = { inkscapeBin.toString(), "--export-width="+TILE_SIZE, "--export-height="+TILE_SIZE, "--export-png="+pngFile.toString(), svgFile.toString() }; Process p = Runtime.getRuntime().exec(cmdline); int exit_value; try { exit_value = p.waitFor(); } catch (InterruptedException e) { throw new RuntimeException(e); } if (exit_value != 0) { throw new RuntimeException("Helper exit status: "+exit_value); } if (!pngFile.exists()) { throw new RuntimeException("File not found: "+pngFile); } } static SourceImage loadImage(String fileName) throws IOException { File svgFile, pngFile; svgFile = new File(fileName+"_"+TILE_SIZE+"x"+TILE_SIZE+".svg"); pngFile = new File(fileName+"_"+TILE_SIZE+"x"+TILE_SIZE+".png"); if (svgFile.exists()) { renderSvg(svgFile, pngFile); } else { svgFile = new File(fileName+".svg"); if (svgFile.exists()) { renderSvg(svgFile, pngFile); } } if (pngFile.exists()) { ImageIcon ii = new ImageIcon(pngFile.toString()); return new SourceImage( ii.getImage(), TILE_SIZE); } pngFile = new File(fileName+".png"); if (pngFile.exists()) { ImageIcon ii = new ImageIcon(pngFile.toString()); return new SourceImage( ii.getImage(), 16); } throw new IOException("File not found: "+fileName+".{svg,png}"); } }