Index: src/test/display/CommonDisplay.java
===================================================================
--- src/test/display/CommonDisplay.java	(revision 229)
+++ src/test/display/CommonDisplay.java	(working copy)
@@ -143,7 +143,7 @@
 	 * @param name The name of the .img file.
 	 * @param fileExt The file to get.  It is found by extension.
 	 */
-	protected void display(String name, String fileExt) {
+	public void display(String name, String fileExt) {
 		if (name.endsWith(fileExt)) {
 			display(name);
 			return;
Index: src/test/display/DemDisplay.java
===================================================================
--- src/test/display/DemDisplay.java	(revision 0)
+++ src/test/display/DemDisplay.java	(revision 0)
@@ -0,0 +1,247 @@
+/*
+ * Copyright (C) 2010.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 or
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+package test.display;
+
+import uk.me.parabola.imgfmt.Utils;
+import uk.me.parabola.imgfmt.app.ImgFileReader;
+
+/**
+ * Standalone program to display the DEM file.  This stores a 
+ * digital elevation model used to display shaded surface and profiles of tracks. 
+ * 
+ * @author Ronny Klier
+ *
+ */
+public class DemDisplay extends CommonDisplay {
+
+	private class DemTile {
+		private DemSection section;
+		private int tileNumberLat;
+		private int tileNumberLon;
+		private int offset;       		// offset from section.dataOffset2
+		private int dataLength;			// number of bytes for compressed elevation data
+		private short baseHeight;		// base or minimum height in this tile 
+		private short differenceHeight;	// maximum height above baseHeight (elevation?)
+		
+		DemTile(DemSection parent, int numLat, int numLon) {
+			section = parent;
+			tileNumberLat = numLat;
+			tileNumberLon = numLon;
+		}
+		
+		void readHeader(ImgFileReader reader, int baseOffset) {
+			Displayer d = new Displayer(reader);
+			d.setTitle("DEM Tile Header");
+			DisplayItem item = d.item();
+			item.addText("Tile row %1$s column %2$s", tileNumberLat, tileNumberLon);
+			
+			reader.position(section.dataOffset + (section.tilesLon * tileNumberLat + tileNumberLon) * section.tileDescSize);
+			
+			switch (section.offsetSize) {
+			case 1:
+				offset = d.byteValue("offset in data section");
+				break;
+			case 2:
+				offset = d.shortValue("offset in data section");
+				break;
+			case 3:
+				offset = d.int3Value("offset in data section");
+				break;
+			}
+			offset += baseOffset; 
+			if (1 == section.baseSize) {
+				baseHeight = d.byteValue("minimum height");
+			} else {
+				baseHeight = d.shortValue("minimum height");
+			}
+			if (1 == section.differenceSize) {
+				differenceHeight = d.byteValue("elevation");
+			} else {
+				differenceHeight = d.shortValue("elevation");
+			}
+			d.print(outStream);
+		}
+		
+		void setDataLength(int nextOffset) {
+			dataLength = nextOffset - offset;
+			if (dataLength < 0)
+				dataLength = 0;
+		}
+
+		public void printRawData(ImgFileReader reader) {
+			reader.position(offset);
+			Displayer d = new Displayer(reader);
+			d.setTitle(String.format("Raw data for tile row %1$s column %2$s", tileNumberLat, tileNumberLon));
+			
+			d.rawValue(dataLength, "real DEM data");
+			d.print(outStream);
+		}
+	}
+	
+	private class DemSection {
+		private int num;
+		private int pointsPerLat;
+		private int pointsPerLon;
+		private int tilesLat;
+		private int tilesLon;
+		private byte offsetSize;
+		private byte baseSize;
+		private byte differenceSize;
+		private short tileDescSize;
+		private int dataOffset;
+		private int dataOffset2;
+		private int pointsDistanceLat;
+		private int pointsDistanceLon;
+		private int top;
+		private int left;
+		
+		private DemTile[] tiles;
+		
+		protected void print(ImgFileReader reader) {
+			readHeader(reader);
+		}
+		
+		private void readHeader(ImgFileReader reader) {
+			Displayer d = new Displayer(reader);
+			d.setTitle("DEM Sector Header");
+			num = d.shortValue("#"); 			//0x00 - 0x01
+			pointsPerLat = d.intValue("Points per tile (latitude"); 	//0x02 - 0x05
+			pointsPerLon = d.intValue("Points per tile (longitude)");//0x06 - 0x09
+			d.intValue("unknown integer1");		//0x0a - 0x0d
+			d.intValue("unknown integer2");		//0x0e - 0x11
+			d.shortValue("unknown short");		//0x12 - 0x13
+			tilesLon = d.intValue("Tiles per longitude") + 1;		//0x14 - 0x17
+			tilesLat = d.intValue("Tiles per latitude") + 1;		//0x18 - 0x1B
+			
+			short recordDesc = d.shortValue("Flags for tile description");		//0x1C - 0x1D
+			DisplayItem item = d.item();
+			offsetSize = (byte)((recordDesc & 3) + 1);
+			baseSize = (byte)(((recordDesc & 4) >> 2) + 1);
+		    differenceSize = (byte)(((recordDesc & 8) >> 3) + 1);
+			item.addText("Data offset has %s bytes", offsetSize);
+			item.addText("Base height has %s bytes", baseSize);
+			item.addText("Height difference has %s bytes", differenceSize);
+			tileDescSize = d.shortValue("Size of tile description");//0x1E - 0x1F
+			
+			dataOffset = d.intValue("offset of first tile description");// 0x20 - 0x23
+			dataOffset2 = d.intValue("offset of first tiles data");		//0x24 - 0x27
+			left = d.intValue("western bound"); 		//0x28-0x2B
+			top = d.intValue("northern bound"); //0x2C - 0x2F
+			d.item().addText("In degrees lat,lon: %.4f,%.4f",
+					DemDisplay.toDegrees(top),
+					DemDisplay.toDegrees(left));
+
+			pointsDistanceLat = d.intValue("map units between points (latitude)");		//0x30 - 0x33
+			pointsDistanceLon = d.intValue("map units between points (longitude)");		//0x34 - 0x37
+			d.shortValue("minimum height");		//0x38 - 0x39
+			d.shortValue("maximum height");		//0x3A - 0x3B
+
+			d.print(outStream);
+			
+			tiles = new DemTile[tilesLat * tilesLon];
+			
+			// now read the tile description
+			for (int i = 0; i < tiles.length; ++i) {
+				tiles[i] = new DemTile(this, i / tilesLon, i % tilesLon);
+				tiles[i].readHeader(reader, dataOffset2);
+				if (i != 0) {
+					tiles[i-1].setDataLength(tiles[i].offset);
+				}
+				// data length of last tile has to be set after reading next section
+			}
+		}
+		
+		private void setLastDataLength(int nextSectionOffset) {
+			tiles[tiles.length -1].setDataLength(nextSectionOffset);
+		}
+
+		public void printRawData(ImgFileReader reader) {
+			Displayer d = new Displayer(reader);
+			d.setTitle(String.format("Printing raw data of sector %s", num));
+			
+			for (int i = 0; i < tiles.length; ++i) {
+				tiles[i].printRawData(reader);
+			}			
+			d.print(outStream);
+		}
+	}
+	
+	private DemSection[] sections;
+	private int sectionOffset;
+	private short sectionSize;
+	private boolean useMeters;
+	
+	@Override
+	protected void print() {
+		readCommonHeader();
+		readFileHeader();
+	}
+	
+	private void readFileHeader() {
+		Displayer d = new Displayer(reader);
+		d.setTitle("DEM Header");
+
+		useMeters = 1 != (d.intValue("Flags ?") & 1);
+		DisplayItem item = d.item();
+		if (useMeters) {
+			item.addText("elevation is given in meters");
+		} else {
+			item.addText("elevation is given in feet");
+		}
+		sections = new DemSection[d.shortValue("Number of zoom levels/sectors")];
+		
+		d.intValue("unknown integer");
+		sectionSize = d.shortValue("size of sector headers");
+		sectionOffset = d.intValue("offset of first sector header");
+		
+		if (getHeaderLen() > 0x25) {
+			d.intValue("unknown integer at 0x25");
+		}
+		
+		d.print(outStream);
+		
+		reader.position(sectionOffset);
+		for (int i = 0; i < sections.length; i++) {
+			reader.position(sectionOffset + sectionSize * i);
+			sections[i] = new DemSection();
+			sections[i].print(reader);
+			if (i != 0) {
+				// data of last tile of previous section ends before first tile of this section
+				sections[i-1].setLastDataLength(sections[i].dataOffset2);
+			} 
+			if (i - 1 == sections.length) {
+				// data of last tile of last section ends before begin of section description
+				sections[i].setLastDataLength(sectionOffset);
+			}
+		}
+		// now iterate a second time over section and tiles and print out raw data
+		for (int i = 0; i < sections.length; ++i) {
+			sections[i].printRawData(reader);
+		}
+	}
+
+	private static double toDegrees(int val) {
+		return (double) val * (360.0 / 4294967296.0);
+	}
+	
+	
+	public static void main(String[] args) {
+		if (args.length < 1) {
+			System.err.println("Usage: demdisplay <filename>");
+			System.exit(1);
+		}
+
+		CommonDisplay td = new DemDisplay();
+		td.display(args[0],"DEM");
+	}
+}
Index: src/test/display/RgnDisplay.java
===================================================================
--- src/test/display/RgnDisplay.java	(revision 229)
+++ src/test/display/RgnDisplay.java	(working copy)
@@ -342,6 +342,7 @@
 
 		} catch (FileNotFoundException e) {
 			System.err.println("Could not open TRE file");
+			return;
 		}
 
 		TREHeader header = (TREHeader) tre.getHeader();
Index: src/test/display/Section.java
===================================================================
--- src/test/display/Section.java	(revision 229)
+++ src/test/display/Section.java	(working copy)
@@ -78,7 +78,7 @@
 	 * Number of items. Only valid when there is a recsize set.
 	 */
 	public int getNumberOfRecords() {
-		return len/ recordSize;
+		return (len == 0) ? 0 : len/ recordSize;
 	}
 
 	public int getMagic() {
