Index: src/uk/me/parabola/mkgmap/CommandArgs.java
===================================================================
--- src/uk/me/parabola/mkgmap/CommandArgs.java	(revision 4807)
+++ src/uk/me/parabola/mkgmap/CommandArgs.java	(working copy)
@@ -27,7 +27,7 @@
 		for (String listOpt : Arrays.asList("mdr7-excl", "mdr7-del", "poi-excl-index", "location-autofill",
 				"overview-levels", "levels", "name-tag-list", "polygon-size-limits", "dem", "dem-dists", "drive-on",
 				"dead-ends", "add-pois-to-lines", "coastlinefile", "generate-sea", "nearby-poi-rules",
-				"line-types-with-direction")) {
+				"line-types-with-direction", "gmapi-minimal")) {
 			stringToList(get(listOpt,  null), listOpt);
 		}
 	}
Index: src/uk/me/parabola/mkgmap/combiners/GmapiBuilder.java
===================================================================
--- src/uk/me/parabola/mkgmap/combiners/GmapiBuilder.java	(revision 4807)
+++ src/uk/me/parabola/mkgmap/combiners/GmapiBuilder.java	(working copy)
@@ -22,6 +22,7 @@
 import java.nio.file.Paths;
 import java.nio.file.StandardCopyOption;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 
@@ -34,6 +35,7 @@
 import uk.me.parabola.imgfmt.fs.FileSystem;
 import uk.me.parabola.imgfmt.fs.ImgChannel;
 import uk.me.parabola.imgfmt.sys.ImgFS;
+import uk.me.parabola.log.Logger;
 import uk.me.parabola.mkgmap.CommandArgs;
 
 import static java.nio.file.StandardOpenOption.*;
@@ -45,9 +47,11 @@
  * each .img file.
  */
 public class GmapiBuilder implements Combiner {
+	private static final Logger log = Logger.getLogger(GmapiBuilder.class);
 	private static final String NS = "http://www.garmin.com/xmlschemas/MapProduct/v1";
 
 	private final Map<String, Combiner> combinerMap;
+	private final Map<String, String> sourceMap;
 
 	private Path gmapDir;
 	private final Map<Integer, ProductInfo> productMap = new HashMap<>();
@@ -58,8 +62,13 @@
 
 	private String typFile;
 
-	public GmapiBuilder(Map<String, Combiner> combinerMap) {
+	private boolean forceWrite;
+	private List<String> mustWritePatterns;
+
+
+	public GmapiBuilder(Map<String, Combiner> combinerMap, Map<String, String> sourceMap) {
 		this.combinerMap = combinerMap;
+		this.sourceMap = sourceMap;
 	}
 
 	/**
@@ -75,6 +84,12 @@
 		productVersion = (short) args.get("product-version", 100);
 
 		gmapDir = Paths.get(args.getOutputDir(), String.format("%s.gmap", familyName));
+		forceWrite = args.exists("gmapi");
+		
+		String forceWritePatterns = args.get("gmapi-minimal", "auto");
+		if ("auto".equals(forceWritePatterns)) 
+			forceWritePatterns = null;
+		mustWritePatterns = CommandArgs.stringToList(forceWritePatterns, "gmapi-minimal");
 	}
 
 	/**
@@ -93,8 +108,10 @@
 
 		// Unzip the image into the product tile directory.
 		try {
-			if (info.isImg())
-				unzipImg(fn, mapname, productId);
+			if (info.isImg()) {
+				if (forceWrite || shouldWrite(info))
+					unzipImg(fn, mapname, productId);
+			}
 			else if (info.getKind() == FileKind.TYP_KIND)
 				typFile = info.getFilename();
 
@@ -103,6 +120,23 @@
 		}
 	}
 
+	private boolean shouldWrite(FileInfo info) {
+		String fn = info.getFilename();
+		String source = sourceMap.get(fn);
+		if (!source.equals(fn)) {
+			log.diagnostic("gmapi-minimal: Writing freshly compiled file " + fn);
+			return true;
+		}
+		for (String pattern : mustWritePatterns) {
+			if (fn.matches(pattern)) {
+				log.diagnostic("gmapi-minimal: Writing old file " + fn + " because it matches pattern " + pattern);
+				return true;
+			}
+		}
+		log.diagnostic("gmapi-minimal: Skipping file " + fn);
+		return false;
+	}
+
 	/**
 	 * The complete map set has been processed.  Finish off anything that needs
 	 * doing.
@@ -157,7 +191,7 @@
 		unzipImg(srcImgName, destDir);
 	}
 
-	private static void unzipImg(String srcImgName, Path destDir) throws IOException {
+	private void unzipImg(String srcImgName, Path destDir) throws IOException {
 		FileSystem fs = ImgFS.openFs(srcImgName);
 		for (DirectoryEntry ent : fs.list()) {
 			String fullname = ent.getFullName();
@@ -168,7 +202,8 @@
 					continue;
 
 				Files.createDirectories(destDir);
-				copyToFile(f, destDir.resolve(name));
+				Path out = destDir.resolve(name);
+				copyToFile(f, out);
 			}
 		}
 	}
Index: src/uk/me/parabola/mkgmap/main/Main.java
===================================================================
--- src/uk/me/parabola/mkgmap/main/Main.java	(revision 4807)
+++ src/uk/me/parabola/mkgmap/main/Main.java	(working copy)
@@ -104,6 +104,7 @@
 	private volatile int programRC = 0;
 
 	private final Map<String, Combiner> combinerMap = new HashMap<>();
+	private final Map<String, String> sourceMap = new HashMap<>();
 	private boolean informationDisplayed = false;
 
 	/**
@@ -297,6 +298,7 @@
 			}
 		});
 		task.setArgs(args);
+		task.setSource(filename);
 		futures.add(task);
 	}
 
@@ -618,6 +620,7 @@
 		final Map<String, Integer> nameToHex = new HashMap<>();
 		for (FilenameTask f : filenames) {
 			if (f.getFilename().endsWith(".img")) {
+				sourceMap.put(f.getFilename(), f.getSource());
 				int hex;
 				try {
 					hex = FileInfo.getFileInfo(f.getFilename() ).getHexname();
@@ -706,10 +709,13 @@
 		boolean indexOpt = args.exists("index");
 		boolean gmapsuppOpt = args.exists("gmapsupp");
 		boolean tdbOpt = args.exists("tdbfile");
-		boolean gmapiOpt = args.exists("gmapi");
+		boolean gmapiOpt = args.exists("gmapi") || args.exists("gmapi-minimal"); 
 		boolean nsisOpt = args.exists("nsis");
 
-		for (String opt : Arrays.asList("gmapi", "nsis")) {
+		if (args.exists("gmapi") && args.exists("gmapi-minimal")) {
+			throw new ExitException("Options --gmapi and --gmapi-minimal are mutually exclusive");
+		}
+		for (String opt : Arrays.asList("gmapi", "nsis", "gmapi-minimal")) {
 			if (!createTdbFiles && args.exists(opt)) {
 				throw new ExitException("Options --" + opt  + " and --no-tdbfiles are mutually exclusive");
 			}
@@ -729,7 +735,7 @@
 			addCombiner("mdx", new MdxBuilder());
 		}
 		if (gmapiOpt) {
-			addCombiner("gmapi", new GmapiBuilder(combinerMap));
+			addCombiner("gmapi", new GmapiBuilder(combinerMap, sourceMap));
 		}
 		if (nsisOpt) {
 			addCombiner("nsis", new NsisBuilder(combinerMap));
@@ -772,6 +778,7 @@
 	private static class FilenameTask extends FutureTask<String> {
 		private CommandArgs args;
 		private String filename;
+		private String source;
 
 		private FilenameTask(Callable<String> callable) {
 			super(callable);
@@ -794,7 +801,16 @@
 		}
 
 		public String toString() {
-			return filename;
+			return source + " -> " + filename;
 		}
+		
+		public void setSource(String source) {
+			this.source = source;
+		}
+
+		public String getSource() {
+			return source;
+		}
+
 	}
 }
