Index: /trunk/ppSub/src/ppSubKernel.c
===================================================================
--- /trunk/ppSub/src/ppSubKernel.c	(revision 19753)
+++ /trunk/ppSub/src/ppSubKernel.c	(revision 19753)
@@ -0,0 +1,116 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <pslib.h>
+#include <psmodules.h>
+
+#define KERNEL_MOSAIC 2                 // Half-number of kernel instances in the mosaic image
+
+
+int main(int argc, char *argv[])
+{
+    if (argc != 3) {
+        fprintf(stderr, "Usage: %s INPUT_KERNEL OUTPUT_IMAGE\n\n", argv[0]);
+        exit(PS_EXIT_SYS_ERROR);
+    }
+
+    const char *inName = argv[1];       // Input file name
+    const char *outName = argv[2];      // Output file name
+
+    psFits *inFile = psFitsOpen(inName, "r"); // Input file
+    if (!inFile) {
+        psErrorStackPrint(stderr, "Unable to open input kernel %s", inName);
+        exit(PS_EXIT_DATA_ERROR);
+    }
+
+    pmReadout *ro = pmReadoutAlloc(NULL); // Readout to hold kernel
+    if (!pmReadoutReadSubtractionKernels(ro, inFile)) {
+        psErrorStackPrint(stderr, "Unable to read input kernel");
+        psFree(ro);
+        psFitsClose(inFile);
+        exit(PS_EXIT_DATA_ERROR);
+    }
+    psFitsClose(inFile);
+
+    pmSubtractionKernels *kernels = psMetadataLookupPtr(NULL, ro->analysis, PM_SUBTRACTION_ANALYSIS_KERNEL);
+    if (!psMemIncrRefCounter(kernels)) {
+        psErrorStackPrint(stderr, "Unable to find input kernel");
+        psFree(ro);
+        exit(PS_EXIT_PROG_ERROR);
+    }
+    psFree(ro);
+
+    pmSubtractionMode mode = kernels->mode; // Mode for subtraction
+    int fullSize = 2 * kernels->size + 1 + 1;    // Full size of kernel
+    int imageSize = (2 * KERNEL_MOSAIC + 1) * fullSize; // Size of image
+    psImage *image = psImageAlloc((mode == PM_SUBTRACTION_MODE_DUAL ? 2 : 1) * imageSize - 1 +
+                                  (mode == PM_SUBTRACTION_MODE_DUAL ? 4 : 0), imageSize - 1, PS_TYPE_F32);
+    psImageInit(image, NAN);
+    for (int j = -KERNEL_MOSAIC; j <= KERNEL_MOSAIC; j++) {
+        for (int i = -KERNEL_MOSAIC; i <= KERNEL_MOSAIC; i++) {
+            psImage *kernel = pmSubtractionKernelImage(kernels, (float)i / (float)KERNEL_MOSAIC,
+                                                       (float)j / (float)KERNEL_MOSAIC,
+                                                       false); // Image of the kernel
+            if (!kernel) {
+                psError(PS_ERR_UNKNOWN, false, "Unable to generate kernel image.");
+                psFree(image);
+                psFree(kernel);
+                psFree(kernels);
+                exit(PS_EXIT_SYS_ERROR);
+            }
+
+            if (psImageOverlaySection(image, kernel, (i + KERNEL_MOSAIC) * fullSize,
+                                      (j + KERNEL_MOSAIC) * fullSize, "=") == 0) {
+                psError(PS_ERR_UNKNOWN, false, "Unable to overlay kernel image.");
+                psFree(kernel);
+                psFree(image);
+                psFree(kernels);
+                exit(PS_EXIT_PROG_ERROR);
+            }
+            psFree(kernel);
+
+            if (mode == PM_SUBTRACTION_MODE_DUAL) {
+                kernel = pmSubtractionKernelImage(kernels, (float)i / (float)KERNEL_MOSAIC,
+                                                  (float)j / (float)KERNEL_MOSAIC,
+                                                  true); // Image of the kernel
+                if (!kernel) {
+                    psError(PS_ERR_UNKNOWN, false, "Unable to generate kernel image.");
+                    psFree(image);
+                    psFree(kernels);
+                    exit(PS_EXIT_SYS_ERROR);
+                }
+
+                if (psImageOverlaySection(image, kernel,
+                                          (2 * KERNEL_MOSAIC + 1 + i + KERNEL_MOSAIC) * fullSize + 4,
+                                          (j + KERNEL_MOSAIC) * fullSize, "=") == 0) {
+                    psError(PS_ERR_UNKNOWN, false, "Unable to overlay kernel image.");
+                    psFree(kernel);
+                    psFree(image);
+                    psFree(kernels);
+                    exit(PS_EXIT_PROG_ERROR);
+                }
+                psFree(kernel);
+            }
+        }
+    }
+    psFree(kernels);
+
+    psFits *outFile = psFitsOpen(outName, "w"); // Output file
+    if (!outFile) {
+        psErrorStackPrint(stderr, "Unable to open output file %s", outName);
+        psFree(image);
+        exit(PS_EXIT_SYS_ERROR);
+    }
+    if (!psFitsWriteImage(outFile, NULL, image, 0, NULL)) {
+        psErrorStackPrint(stderr, "Unable to write output file");
+        psFree(image);
+        psFitsClose(outFile);
+        exit(PS_EXIT_SYS_ERROR);
+    }
+    psFitsClose(outFile);
+    psFree(image);
+
+    exit(PS_EXIT_SUCCESS);
+}
