Index: test/uk/me/parabola/imgfmt/app/BitReaderTest.java
===================================================================
--- test/uk/me/parabola/imgfmt/app/BitReaderTest.java	(revision 3678)
+++ test/uk/me/parabola/imgfmt/app/BitReaderTest.java	(working copy)
@@ -46,7 +46,14 @@
 		int s = br.sget2(3);
 		assertEquals(-12, s);
 	}
+	@Test
+	public void testSpecialNegative2() {
+		BitReader br = new BitReader(new byte[]{0x2c, 0x0});
 
+		int s = br.sget2(3);
+		assertEquals(-6, s);
+	}
+
 	@Test
 	public void testSpecialPositive() {
 		BitReader br = new BitReader(new byte[]{(byte) 0xa4, 0});
@@ -54,4 +61,18 @@
 		int s = br.sget2(3);
 		assertEquals(8, s);
 	}
+	
+	@Test
+	public void testWriteRead() {
+		for (int i = -20; i <= 20; i++){
+			BitWriter bw = new BitWriter();
+			bw.sputn(i,3);
+			BitReader br = new BitReader(bw.getBytes());
+
+			int s = br.sget2(3);
+			assertEquals(i, s);
+		}
+	}
+	
+	
 }
Index: src/uk/me/parabola/imgfmt/app/BitReader.java
===================================================================
--- src/uk/me/parabola/imgfmt/app/BitReader.java	(revision 3678)
+++ src/uk/me/parabola/imgfmt/app/BitReader.java	(working copy)
@@ -99,9 +99,9 @@
 		// appropriate.
 		if ((res & top) == 0)
 			res += base;
-		else
+		else {
 			res = (res | ~mask) - base; // Make negative and subtract the base
-
+		}
 		return res;
 	}
 
Index: src/uk/me/parabola/imgfmt/app/BitWriter.java
===================================================================
--- src/uk/me/parabola/imgfmt/app/BitWriter.java	(revision 3678)
+++ src/uk/me/parabola/imgfmt/app/BitWriter.java	(working copy)
@@ -110,7 +110,22 @@
 
 		buflen = (bitoff+7)/8;
 	}
-
+	
+	public void sputn(int bval, int nb) {
+		int top = 1 << (nb - 1);
+		int mask = top - 1;
+		int val = Math.abs(bval);
+		while (val > mask) {
+			putn(top, nb);
+			val -= mask;
+		}
+		if (bval < 0) {
+			putn((top - val) | top, nb);
+		} else {
+			putn(val, nb);
+		}
+	}
+	
 	public byte[] getBytes() {
 		return buf;
 	}
Index: src/uk/me/parabola/imgfmt/app/trergn/LinePreparer.java
===================================================================
--- src/uk/me/parabola/imgfmt/app/trergn/LinePreparer.java	(revision 3678)
+++ src/uk/me/parabola/imgfmt/app/trergn/LinePreparer.java	(working copy)
@@ -69,11 +69,163 @@
 
 	/**
 	 * Write the bit stream to a BitWriter and return it.
+	 * Try different values for xBase and yBase to find the best one.
+	 * 
+	 * @return A class containing the written byte stream.
+	 */
+	public BitWriter makeBitStream(int minPointsRequired) {
+		BitWriter bs = makeBitStream(minPointsRequired, xBase, yBase);
+		int xBestBase = xBase;
+		int yBestBase = yBase;
+		int origLength = bs.getLength();
+		if (xBase > 0){
+			boolean xSameSignBak = xSameSign;
+			xSameSign = false;
+			for (int xTestBase = xBase-1; xTestBase >= 0; xTestBase--){
+				BitWriter bstest = makeBitStream(minPointsRequired, xTestBase, yBase);
+//				System.out.println(xBase + " "  + testXBase + " -> " + bs.getLength() + " " + bstest.getLength());
+				if (bstest.getLength() >= bs.getLength()){
+					break;
+				} else {
+					xBestBase = xTestBase;
+					bs = bstest;
+					xSameSignBak = false;
+				}
+			}
+			xSameSign = xSameSignBak;
+		}
+		if (yBase > 0){
+			boolean ySameSignBak = ySameSign;
+			ySameSign = false;
+			for (int yTestBase = yBase-1; yTestBase >= 0; yTestBase--){
+				BitWriter bstest = makeBitStream(minPointsRequired, xBestBase, yTestBase);
+//				System.out.println(yBase + " "  + testYBase + " -> " + bs.getLength() + " " + bstest.getLength());
+				if (bstest.getLength() >= bs.getLength()){
+					break;
+				} else {
+					bs = bstest;
+					ySameSignBak = false;
+				}
+			}
+			ySameSign = ySameSignBak;
+		}
+		if (log.isInfoEnabled()){
+			if (xBase != xBestBase || yBestBase != yBase){
+				log.info("optimizer reduced bit stream length from",origLength,"->",bs.getLength(),"(" + (origLength-bs.getLength()), " byte(s)) for",polyline.getClass().getSimpleName(),"with",polyline.getPoints().size(),"points");
+			}
+		}
+		return bs;
+	}
+	/**
+	 * Write the bit stream to a BitWriter and return it.
 	 *
 	 * @return A class containing the written byte stream.
 	 */
-	public BitWriter makeBitStream(int minPointsRequired) {
+	public BitWriter makeBitStream(int minPointsRequired, int xb, int yb) {
 
+		assert xb >= 0 && yb >= 0;
+		
+		int xbits = 2;
+		if (xb < 10)
+			xbits += xb;
+		else
+			xbits += (2 * xb) - 9;
+
+		int ybits = 2;
+		if (yb < 10)
+			ybits += yb;
+		else
+			ybits += (2 * yb) - 9;
+
+			
+		// Note no sign included.
+		if (log.isDebugEnabled())
+			log.debug("xbits", xbits, ", y=", ybits);
+
+		// Write the bitstream
+		BitWriter bw = new BitWriter();
+
+		// Pre bit stream info
+		bw.putn(xb, 4);
+		bw.putn(yb, 4);
+
+		bw.put1(xSameSign);
+		if (xSameSign)
+			bw.put1(xSignNegative);
+
+		bw.put1(ySameSign);
+		if (ySameSign)
+			bw.put1(ySignNegative);
+
+		if (log.isDebugEnabled()) {
+			log.debug("x same is", xSameSign, "sign is", xSignNegative);
+			log.debug("y same is", ySameSign, "sign is", ySignNegative);
+		}
+
+		if(extTypeLine) {
+			bw.put1(false);		// no extra bits required
+		}
+
+		// first extra bit always appears to be false
+		// refers to the start point?
+		if (extraBit)
+			bw.put1(false);
+
+		int numPointsEncoded = 1;
+		for (int i = 0; i < deltas.length; i+=2) {
+			int dx = deltas[i];
+			int dy = deltas[i + 1];
+			if (dx == 0 && dy == 0){
+				if (extraBit && nodes[i/2+1] == false && i+2 != deltas.length) // don't skip CoordNode
+					continue;
+			}
+			++numPointsEncoded;
+
+			if (log.isDebugEnabled())
+				log.debug("x delta", dx, "~", xbits);
+//			assert dx >> xbits == 0 || dx >> xbits == -1;
+			if (xSameSign) {
+				bw.putn(Math.abs(dx), xbits);
+			} else {
+				// catch inadvertent output of "magic" value that has
+				// sign bit set but other bits all 0
+//				assert dx >= 0 || (dx & ((1 << xbits) - 1)) != 0;
+//				bw.putn(dx, xbits);
+//				bw.put1(dx < 0);
+				bw.sputn(dx, xbits+1);
+			}
+
+			if (log.isDebugEnabled())
+				log.debug("y delta", dy, ybits);
+//			assert dy >> ybits == 0 || dy >> ybits == -1;
+			if (ySameSign) {
+				bw.putn(Math.abs(dy), ybits);
+			} else {
+				// catch inadvertent output of "magic" value that has
+				// sign bit set but other bits all 0
+//				assert dy >= 0 || (dy & ((1 << ybits) - 1)) != 0;
+//				bw.putn(dy, ybits);
+//				bw.put1(dy < 0);
+				bw.sputn(dy, ybits+1);
+			}
+			if (extraBit)
+				bw.put1(nodes[i/2+1]);
+		}
+
+		if (log.isDebugEnabled())
+			log.debug(bw);
+
+		if(numPointsEncoded < minPointsRequired)
+			return null;
+
+		return bw;
+	}
+	/**
+	 * Write the bit stream to a BitWriter and return it.
+	 *
+	 * @return A class containing the written byte stream.
+	 */
+	public BitWriter makeBitStream2(int minPointsRequired) {
 		assert xBase >= 0 && yBase >= 0;
 
 		int xbits = 2;
Index: src/uk/me/parabola/mkgmap/filters/PolygonSplitterBase.java
===================================================================
--- src/uk/me/parabola/mkgmap/filters/PolygonSplitterBase.java	(revision 3678)
+++ src/uk/me/parabola/mkgmap/filters/PolygonSplitterBase.java	(working copy)
@@ -28,7 +28,7 @@
  * @author Steve Ratcliffe
  */
 public class PolygonSplitterBase extends BaseFilter {
-	protected static final int MAX_SIZE = 0x7fff;
+	protected static final int MAX_SIZE = 0xffff;
 	private int shift;
 	
 	public void init(FilterConfig config) {
