Index: src/uk/me/parabola/imgfmt/app/dem/DEMFile.java
===================================================================
--- src/uk/me/parabola/imgfmt/app/dem/DEMFile.java	(revision 4107)
+++ src/uk/me/parabola/imgfmt/app/dem/DEMFile.java	(working copy)
@@ -21,6 +21,7 @@
 import uk.me.parabola.imgfmt.app.ImgFile;
 import uk.me.parabola.imgfmt.app.ImgFileWriter;
 import uk.me.parabola.imgfmt.fs.ImgChannel;
+import uk.me.parabola.log.Logger;
 import uk.me.parabola.mkgmap.reader.hgt.HGTConverter;
 import uk.me.parabola.mkgmap.reader.hgt.HGTConverter.InterpolationMethod;
 
@@ -31,8 +32,11 @@
  * @author Gerd Petermann
  */
 public class DEMFile extends ImgFile {
+	private static final Logger log = Logger.getLogger(DEMFile.class);
+
 	// allowed increase of DEM area
-	public final static double EXTRA = 0.01d; 
+	public final static double EXTRA = 0.1d; 
+	protected final static double FACTOR = 45.0d / (1<<29);
 	
 	private final DEMHeader demHeader = new DEMHeader();
 
@@ -54,8 +58,9 @@
 	 * @param pathToHGT comma separated list of directories or zip files
 	 * @param pointDistances list of distances which determine the resolution
 	 * @param outsidePolygonHeight the height value that should be used for points outside of the bounding polygon
+	 * @return a new bounding box that should be used for the TRE file 
 	 */
-	public void calc(Area area, java.awt.geom.Area demPolygonMapUnits, String pathToHGT, List<Integer> pointDistances, short outsidePolygonHeight, InterpolationMethod interpolationMethod) {
+	public Area calc(Area area, java.awt.geom.Area demPolygonMapUnits, String pathToHGT, List<Integer> pointDistances, short outsidePolygonHeight, InterpolationMethod interpolationMethod) {
 		// HGT area is extended by EXTRA degrees in each direction
 		HGTConverter hgtConverter = new HGTConverter(pathToHGT, area, demPolygonMapUnits, EXTRA);
 		hgtConverter.setInterpolationMethod(interpolationMethod);
@@ -65,7 +70,8 @@
 		int bottom = area.getMinLat() * 256;
 		int left = area.getMinLong() * 256;
 		int right = area.getMaxLong() * 256;
-
+		Area demArea = null;
+		
 		int zoom = 0;
 		int lastDist = pointDistances.get(pointDistances.size()-1); 
 		for (int pointDist : pointDistances) {
@@ -77,36 +83,64 @@
 			// last 4 bits of distance should be 0
 			distance = ((distance + 8)/16)*16;
 
-			int xtop = top;
-			int xleft = left;
-
+			int xTop = top;
+			int xLeft = left;
+			
 			// align DEM to distance raster, if distance not bigger than widening of HGT area
 			if (distance < (int)Math.floor((EXTRA/45.0D * (1 << 29)))) {
-				if (xtop >= 0) {
-					xtop -= xtop % distance;
-					if (xtop < 0x3FFFFFFF - distance)
-						xtop += distance;
-				}
-				else {
-					xtop -= xtop % distance;
-				}
-
-				if (xleft >= 0) {
-					xleft -= xleft % distance;
-				}
-				else {
-					xleft -= xleft % distance;
-					if (xleft > Integer.MIN_VALUE + distance)
-						xleft -= distance;
-				}
+				xTop = moveUp(top, distance);
+				xLeft = moveLeft(left, distance);
 			}
-
-			DEMSection section = new DEMSection(zoom++, xtop, xleft, xtop - bottom, right - xleft, hgtConverter, distance, pointDist == lastDist);
+			
+			DEMSection section = new DEMSection(zoom++, xTop, xLeft, xTop - bottom, right - xLeft, hgtConverter, distance, pointDist == lastDist);
 			demHeader.addSection(section);
+			if (demArea == null) {
+				int xBottom = moveUp(bottom, distance);
+				int xRight = moveLeft(right, distance);
+				int demLeft = xLeft / 256;
+				int demRight = xRight / 256 + 1 ;
+				int demTop = xTop / 256;
+				int demBottom = xBottom / 256 - 1;
+				int alignment = 2;
+				while (demLeft % alignment != 0)
+					--demLeft;
+				while (demRight % alignment != 0)
+					++demRight;
+				while (demTop % alignment != 0)
+					++demTop;
+				while (demBottom % alignment != 0)
+					--demBottom;
+				demArea = new Area(demBottom, demLeft, demTop, demRight);
+			}
 		}
-		return;
+		return demArea;
 	}
 
+	int moveUp(int origLat32, int distance) {
+		int moved = origLat32;
+		if (moved >= 0) {
+			moved -= moved % distance;
+			if (moved < 0x3FFFFFFF - distance)
+				moved += distance;
+		} else {
+			moved -= moved % distance;
+		}
+		return moved;
+	}
+	
+	int moveLeft (int origLon32, int distance) {
+		int moved = origLon32;
+		if (moved >= 0) {
+			moved -= moved % distance;
+		}
+		else {
+			moved -= moved % distance;
+			if (moved > Integer.MIN_VALUE + distance)
+				moved -= distance;
+		}
+		return moved;
+	}
+	
 	public void write() {
 		ImgFileWriter w = getWriter();
 		if (w instanceof BufferedImgFileWriter) {
Index: src/uk/me/parabola/imgfmt/app/dem/DEMSection.java
===================================================================
--- src/uk/me/parabola/imgfmt/app/dem/DEMSection.java	(revision 4107)
+++ src/uk/me/parabola/imgfmt/app/dem/DEMSection.java	(working copy)
@@ -59,8 +59,8 @@
 		// allow automatic selection of interpolation method for each zoom level
 		hgtConverter.startNewLevel(pointDist);
 
-		int []latInfo = getTileInfo(areaHeight, pointsDistanceLat);
-		int []lonInfo = getTileInfo(areaWidth, pointsDistanceLon);
+		int[] latInfo = getTileInfo(areaHeight, pointsDistanceLat);
+		int[] lonInfo = getTileInfo(areaWidth, pointsDistanceLon);
 		// store the values written to the header
 		tilesLat = latInfo[0];
 		tilesLon = lonInfo[0];
@@ -68,7 +68,6 @@
 		nonStdWidth = lonInfo[1];
 		log.info("calculating zoom level:",zoomLevel,", dist:",pointDist,tilesLon,"x",tilesLat,"std tiles, nonstd x/y",nonStdWidth,"/",nonStdHeight);
 		calcTiles(hgtConverter);
-		hgtConverter = null;
 	}
 
 	/**
@@ -126,8 +125,7 @@
 				tiles.add(tile);
 				if (tile.getEncodingType() != 0)
 					hasExtra = true;
-				int bsLen = tile.getBitStreamLen();
-				if (bsLen > 0) {
+				if (tile.hasValidHeights()) {
 					if (tile.getBaseHeight() < minBaseHeight)
 						minBaseHeight = tile.getBaseHeight();
 					if (tile.getBaseHeight() > maxBaseHeight)
@@ -136,8 +134,8 @@
 						maxHeight = tile.getMaxHeight();
 					if (tile.getMaxDeltaHeight() > maxDeltaHeight)
 						maxDeltaHeight = tile.getMaxDeltaHeight();
-					dataLen += bsLen;
 				}
+				dataLen += tile.getBitStreamLen();
 			}
 			if (lastLevel) {
 				hgtConverter.freeMem();
Index: src/uk/me/parabola/imgfmt/app/dem/DEMTile.java
===================================================================
--- src/uk/me/parabola/imgfmt/app/dem/DEMTile.java	(revision 4107)
+++ src/uk/me/parabola/imgfmt/app/dem/DEMTile.java	(working copy)
@@ -13,7 +13,6 @@
 package uk.me.parabola.imgfmt.app.dem;
 
 import java.io.ByteArrayOutputStream;
-import java.util.Arrays;
 
 import uk.me.parabola.imgfmt.MapFailedException;
 import uk.me.parabola.imgfmt.app.ImgFileWriter;
@@ -43,6 +42,7 @@
 	private final int baseHeight;		// base or minimum height in this tile 
 	private final int maxDeltaHeight;	// delta between max height and base height
 	private final byte encodingType;  	// determines how the highest values are displayed 
+	private final boolean hasData;		// not all voids
 
 	private int bitPos;
 	private byte currByte;
@@ -94,18 +94,18 @@
 		}
 		if (min == Integer.MAX_VALUE) {
 			// all values are invalid 
+			hasData = false;
 			encodingType = 2;
 			min = 0;
-			max = 1;
-			// seems we still need a bit stream in this case
-			realHeights = new short[width * height];
-			Arrays.fill(realHeights, HGTReader.UNDEF);
+			max = 0;
 		} else if (countInvalid > 0) {
 			// some values are invalid
+			hasData = true;
 			encodingType = 2; // don't display highest value 
 			max++;
 		} else {
 			// all height values are valid
+			hasData = true;
 			encodingType = 0;
 		}
 
@@ -117,12 +117,16 @@
 		createBitStream(realHeights);
 	}
 	
+	public boolean hasValidHeights() {
+		return hasData;
+	}
+
 	public int getBaseHeight() {
 		return baseHeight;
 	}
 
 	public int getMaxHeight() {
-		return baseHeight + maxDeltaHeight; // TODO: does it depend on value in encodingType?
+		return baseHeight + maxDeltaHeight - (encodingType == 0 ? 0 : 1); 
 	}
 	
 	private void createBitStream(short[] realHeights) {
Index: src/uk/me/parabola/mkgmap/build/MapBuilder.java
===================================================================
--- src/uk/me/parabola/mkgmap/build/MapBuilder.java	(revision 4107)
+++ src/uk/me/parabola/mkgmap/build/MapBuilder.java	(working copy)
@@ -298,7 +298,6 @@
 
 		rgnFile.write();
 		treFile.write(rgnFile.haveExtendedTypes());
-		treFile.writePost();
 		lblFile.write();
 		lblFile.writePost();
 
@@ -318,6 +317,7 @@
 			}
 			netFile.writePost(rgnFile.getWriter());
 		}
+		warnAbout3ByteImgRefs();
 		if (demFile != null) {
 			try{
 				long t1 = System.currentTimeMillis();
@@ -337,7 +337,8 @@
 						demArea = new java.awt.geom.Area(demPoly);
 					}
 				}
-				demFile.calc(src.getBounds(), demArea, pathToHGT, demDists, demOutsidePolygonHeight, demInterpolationMethod);
+				Area demBounds = demFile.calc(src.getBounds(), demArea, pathToHGT, demDists, demOutsidePolygonHeight, demInterpolationMethod);
+				map.setBounds(demBounds);
 				long t2 = System.currentTimeMillis();
 				log.info("DEM file calculation for", map.getFilename(), "took", (t2 - t1), "ms");
 				demFile.write();
@@ -346,7 +347,7 @@
 				throw new MapFailedException("DEM"); //TODO: better remove DEM file?
 			}
 		}
-		warnAbout3ByteImgRefs();
+		treFile.writePost();
 	}
 
 	private void warnAbout3ByteImgRefs() {
