Index: trunk/ppImage/src/Makefile.am
===================================================================
--- trunk/ppImage/src/Makefile.am	(revision 20773)
+++ trunk/ppImage/src/Makefile.am	(revision 20774)
@@ -17,4 +17,5 @@
 	ppImageDetrendNonLinear.c \
 	ppImageDetrendFringe.c \
+	ppImageDetrendFree.c \
 	ppImageRebinReadout.c \
 	ppImageMosaic.c \
Index: trunk/ppImage/src/ppImage.h
===================================================================
--- trunk/ppImage/src/ppImage.h	(revision 20773)
+++ trunk/ppImage/src/ppImage.h	(revision 20774)
@@ -128,4 +128,7 @@
 pmReadout* ppImageDetrendSelectFirst(pmCell *cell, char *name, bool doThis);
 
+bool ppImageDetrendFree(pmConfig *config, pmFPAview *view);
+bool ppImageFringeFree(pmConfig *config, pmFPAview *view);
+
 // Record which detrend file was used for the detrending
 bool ppImageDetrendRecord(
Index: trunk/ppImage/src/ppImageDetrendFree.c
===================================================================
--- trunk/ppImage/src/ppImageDetrendFree.c	(revision 20774)
+++ trunk/ppImage/src/ppImageDetrendFree.c	(revision 20774)
@@ -0,0 +1,69 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "ppImage.h"
+
+// list of the detrend types to free
+static char *detrendTypes[] = {
+    "PPIMAGE.MASK",
+    "PPIMAGE.BIAS",
+    "PPIMAGE.DARK",
+    "PPIMAGE.FLAT",
+    "PPIMAGE.SHUTTER",
+    NULL
+};
+
+bool ppImageDetrendFree (pmConfig *config, pmFPAview *view) {
+
+    bool status;
+
+    for (int i = 0; detrendTypes[i] != NULL; i++) {
+
+	pmFPAfile *file = psMetadataLookupPtr(&status, config->files, detrendTypes[i]); // File of interest
+	if (!file) continue; // not all detrends are used in any given run
+
+	// this only returns false on a failure.  if we are not ready to write or close, it is not an error
+	if (!pmFPAfileWrite (file, view, config)) {
+	    psError(PS_ERR_IO, false, "failed to WRITE %s", file->name);
+	    return false;
+	}
+	if (!pmFPAfileClose(file, view)) {
+	    psError(PS_ERR_IO, false, "failed to CLOSE for %s", file->name);
+	    return false;
+	}
+	if (!pmFPAfileFreeData(file, view)) {
+	    if (!psMetadataRemoveKey(config->files, file->name)) {
+		psError(PS_ERR_IO, false, "failed to remove %s in FPA_AFTER block", file->name);
+		return false;
+	    }
+	}
+    }
+    return true;
+}
+
+bool ppImageFringeFree (pmConfig *config, pmFPAview *view) {
+
+    bool status;
+
+    pmFPAfile *file = psMetadataLookupPtr(&status, config->files, "PPIMAGE.FRINGE"); // File of interest
+    if (!file) return true;
+
+    // this only returns false on a failure.  if we are not ready to write or close, it is not an error
+    if (!pmFPAfileWrite (file, view, config)) {
+	psError(PS_ERR_IO, false, "failed to WRITE %s", file->name);
+	return false;
+    }
+    if (!pmFPAfileClose(file, view)) {
+	psError(PS_ERR_IO, false, "failed to CLOSE for %s", file->name);
+	return false;
+    }
+    if (!pmFPAfileFreeData(file, view)) {
+	if (!psMetadataRemoveKey(config->files, file->name)) {
+	    psError(PS_ERR_IO, false, "failed to remove %s in FPA_AFTER block", file->name);
+	    return false;
+	}
+    }
+
+    return true;
+}
