Attention! Do you have any ideas for reorganizing and updating the Mapki? Please leave a note here. Thank you!

Java Tile Cutter

From Google Mapki

Jump to: navigation, search

[edit] Tiler.java


package com.ti.gmap;

import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Iterator;

import javax.imageio.ImageIO;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.ImageWriter;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.ImageOutputStream;

/**
 * Tiler - generates tiles and html
 * 
 * <br/> Usage: java com.ti.gmap.Tiler directory imagefile
 * 
 * @author Eric
 * 
 */
public class Tiler {

	/**
	 * @param args
	 * @throws IOException
	 * @throws Exception
	 */
	public static void main(String[] args) throws Exception {

		if (args.length != 3) {
			System.out.println("Usage: java " + Tiler.class.getName()
					+ " <dir> <file> <key>");
			return;
		}

		File dir = new File(args[0]);
		File file = new File(args[1]);
		String gmapApiKey = args[2];
		Tiler tiler = new Tiler();
		tiler.tile(dir, file, gmapApiKey);

	}

	private File outputDir;
	private String filePrefix;
	private String fileSuffix;
	private ImageWriter imageWriter;
	private int maxZoom;
	private String gmapApiKey;
	private int imageSize;
	private ImageTypeSpecifier imageType;
	private static final int TILE_SIZE = 256;
	private static final int TILE_QUAD = 128;

	private int calcMaxZoom(int size) {
		int zoom = 0;
		size >>= 8;
		while (size > 1) {
			size >>= 1;
			++zoom;
		}
		return zoom;
	}

	private String getFileName(int z, int y, int x) {
		return filePrefix + "_" + z + "_" + y + "_" + x + "." + fileSuffix;
	}

	private void html(int z) throws IOException {

		int max = 1 << z;

		File file = new File(outputDir, filePrefix + "_" + z + ".html");
		PrintWriter out = new PrintWriter(file);

		out.println("<html>");
		out.println("<body>");
		out.println("<table border=\"1\" cellspacing=\"0\" cellpadding=\"0\">");
		for (int y = 0; y < max; y++) {
			out.println("<tr>");
			for (int x = 0; x < max; x++) {
				final String fileName = getFileName(z, y, x);
				out.println("<td><img src=\"" + fileName
						+ "\" border=\"0\" /></td>");
			}
			out.println("</tr>");
		}
		out.println("</table>");
		out.println("</body>");
		out.println("</html>");

		out.close();
	}

	public void tile(File dir, File file, String gmapApiKey) throws IOException {
		tile(dir, file, gmapApiKey, file.getName(), file.lastModified());
	}

	public void tile(File dir, File file, String gmapApiKey, String fileName,
			long lastModified) throws IOException {

		this.outputDir = dir;
		this.gmapApiKey = gmapApiKey;

		int p = fileName.lastIndexOf('.');
		this.filePrefix = fileName.substring(0, p);
		this.fileSuffix = fileName.substring(p + 1);

		ImageInputStream imageInputStream = ImageIO
				.createImageInputStream(file);

		Iterator<ImageReader> imageReaders = ImageIO
				.getImageReaders(imageInputStream);
		ImageReader imageReader = imageReaders.next();

		imageReader.setInput(imageInputStream);
		int imageIndex = imageReader.getMinIndex();

		Iterator<ImageWriter> imageWriters = ImageIO
				.getImageWritersBySuffix(fileSuffix);
		imageWriter = imageWriters.next();

		Iterator<ImageTypeSpecifier> imageTypes = imageReader
				.getImageTypes(imageIndex);
		imageType = imageTypes.next();

		int width = imageReader.getWidth(imageIndex);
		int height = imageReader.getHeight(imageIndex);

		imageSize = Math.max(width, height);
		maxZoom = calcMaxZoom(imageSize);

		ImageReadParam readParam = imageReader.getDefaultReadParam();

		map();

		for (int i = 0; i <= maxZoom; i++) {
			html(i);
		}

		int floorSize = 2048;
		if (imageSize < floorSize) {
			floorSize = imageSize;
		}
		Rectangle floorRegion = new Rectangle(0, 0, floorSize, floorSize);
		final int tileSize = 256;
		Rectangle tileRegion = new Rectangle(0, 0, tileSize, tileSize);

		final int tileFloorLength = floorSize / tileSize;

		Point tile = new Point(0, 0);
		Point floor = new Point(0, 0);

		for (floor.y = 0, floorRegion.y = 0; floorRegion.y < imageSize; floor.y += tileFloorLength, floorRegion.y += floorSize) {
			for (floor.x = 0, floorRegion.x = 0; floorRegion.x < imageSize; floor.x += tileFloorLength, floorRegion.x += floorSize) {
				readParam.setSourceRegion(floorRegion);
				BufferedImage img = imageReader.read(imageIndex, readParam);

				for (tile.y = 0, tileRegion.y = 0; tile.y < tileFloorLength; tile.y++, tileRegion.y += tileSize) {
					for (tile.x = 0, tileRegion.x = 0; tile.x < tileFloorLength; tile.x++, tileRegion.x += tileSize) {
						BufferedImage tileImage = img.getSubimage(tileRegion.x,
								tileRegion.y, tileRegion.width,
								tileRegion.height);
						String tileName = getFileName(maxZoom,
								floor.y + tile.y, floor.x + tile.x);
						System.out.println(tileName);
						File tileFile = new File(outputDir, tileName);
						write(tileImage, tileFile);
					}
				}
			}
		}

		imageReader.dispose();
		imageReader = null;
		imageInputStream.close();
		imageInputStream = null;

		BufferedImage bi = tile(0, 0, 0);
		bi.flush();

		imageWriter.dispose();
		imageWriter = null;
	}

	private void map() throws IOException {

		String html = getResourceAsString("map.html");
		String mapJs = getResourceAsString("map.js");

		String initJs = "";
		initJs += "var tilePrefix='" + filePrefix + "';\n";
		initJs += "var tileSuffix='" + fileSuffix + "';\n";
		initJs += "var tileMaxZoom=" + maxZoom + ";\n";
		html = html.replace("%GMAP_KEY%", gmapApiKey);
		html = html.replace("%INIT_JS%", initJs);
		html = html.replace("%MAP_JS%", mapJs);

		File file = new File(outputDir, "index.html");
		PrintWriter out = new PrintWriter(file);
		out.print(html);
		out.close();
	}

	private String getResourceAsString(String name) {
		InputStream in = getClass().getResourceAsStream(name);
		return convertStreamToString(in);
	}

	private String convertStreamToString(InputStream is) {
		BufferedReader reader = new BufferedReader(new InputStreamReader(is));
		StringBuilder sb = new StringBuilder();

		String line = null;
		try {
			while ((line = reader.readLine()) != null) {
				sb.append(line + "\n");
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				is.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		return sb.toString();
	}

	BufferedImage tile(int tx, int ty, int tz) throws IOException {

		final String fileName = getFileName(tz, ty, tx);
		final File file = new File(outputDir, fileName);

		if (tz == maxZoom) {
			return ImageIO.read(file);
		}

		BufferedImage img = imageType.createBufferedImage(TILE_SIZE, TILE_SIZE);

		tz += 1;
		tx <<= 1;
		ty <<= 1;

		Graphics2D g = (Graphics2D) img.getGraphics();
		g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
				RenderingHints.VALUE_INTERPOLATION_BILINEAR);

		draw(g, tx, ty, tz, 0, 0);
		draw(g, tx + 1, ty, tz, TILE_QUAD, 0);
		draw(g, tx, ty + 1, tz, 0, TILE_QUAD);
		draw(g, tx + 1, ty + 1, tz, TILE_QUAD, TILE_QUAD);

		write(img, file);

		System.out.println(fileName);
		return img;
	}

	private void draw(Graphics2D g, int tx, int ty, int tz, int x, int y)
			throws IOException {
		BufferedImage bi = tile(tx, ty, tz);
		g.drawImage(bi, x, y, TILE_QUAD, TILE_QUAD, null);
		bi.flush();
	}

	private void write(BufferedImage img, File file) throws IOException {

		ImageOutputStream output = ImageIO.createImageOutputStream(file);
		imageWriter.setOutput(output);
		try {
			imageWriter.write(img);
			output.close();
		} catch (IOException e) {
			if (output != null) {
				try {
					output.close();
				} catch (IOException e1) {
				}
			}
			if (file.exists()) {
				file.delete();
			}
			throw e;
		}
	}

}

[edit] map.html


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
	xmlns:v="urn:schemas-microsoft-com:vml">
<head>
<title></title>
<script
	src="http://maps.google.com/maps?file=api&v=2&key=%GMAP_KEY%"
	type="text/javascript"></script>
<script type="text/javascript">
%INIT_JS%
%MAP_JS%
</script>
</head>
<body onload="load()" onunload="GUnload()">
<div id="map_canvas" style="height: 800px"></div>
</body>
</html>

[edit] map.js


// ====== Create the Euclidean Projection for the flat map ======
// == Constructor ==
function EuclideanProjection(a){
	this.pixelsPerLonDegree=[];
	this.pixelsPerLonRadian=[];
	this.pixelOrigo=[];
	this.tileBounds=[];
	var b=256;
	var c=1;
	for(var d=0;d<a;d++){
		var e=b/2;
		this.pixelsPerLonDegree.push(b/360);
		this.pixelsPerLonRadian.push(b/(2*Math.PI));
		this.pixelOrigo.push(new GPoint(e,e));
		this.tileBounds.push(c);
		b*=2;
		c*=2;
	}
};

// == Attach it to the GProjection() class ==
EuclideanProjection.prototype = new GProjection();


// == A method for converting latitudes and longitudes to pixel coordinates == 
EuclideanProjection.prototype.fromLatLngToPixel=function(a,b){
	var c=Math.round(this.pixelOrigo[b].x+a.lng()*this.pixelsPerLonDegree[b]);
	var d=Math.round(this.pixelOrigo[b].y+(-2*a.lat())*this.pixelsPerLonDegree[b]);
	return new GPoint(c,d);
};

// == a method for converting pixel coordinates to latitudes and longitudes ==
EuclideanProjection.prototype.fromPixelToLatLng=function(a,b,c){
	var d=(a.x-this.pixelOrigo[b].x)/this.pixelsPerLonDegree[b];
	var e=-0.5*(a.y-this.pixelOrigo[b].y)/this.pixelsPerLonDegree[b];
	return new GLatLng(e,d,c);
};

// == a method that checks if the x,y value is in range ==
EuclideanProjection.prototype.tileCheckRange=function(a,b,c){
	var d=this.tileBounds[b];
	return 0 <= a.y && a.y < d 
		&& 0 <= a.x && a.x < d;
};

// == a method that returns the width of the tilespace ==      
EuclideanProjection.prototype.getWrapWidth=function(zoom) {
	return this.tileBounds[zoom]*256;
};

function load() {

	if (!GBrowserIsCompatible()) {
		return;
	}

	var projection = new EuclideanProjection(tileMaxZoom+1);

	// create a custom picture layer
	var customTileLayer = new GTileLayer(null, 0, tileMaxZoom, {
		isPng :(tileSuffix=='png'),
		tileUrlTemplate :(tilePrefix + '_{Z}_{Y}_{X}.' + tileSuffix)
	});
	var customMap = new GMapType( [ customTileLayer ], projection, "floormap");

	map = new GMap2(document.getElementById("map_canvas"), {
		mapTypes : [ customMap ]
	});
	map.addControl(new GLargeMapControl());
	map.enableScrollWheelZoom();
	map.enableContinuousZoom();

	// initialize map
	map.setCenter(new GLatLng(0, 0), 0);

}

Personal tools
Advertisement