Index: trunk/psModules/src/camera/pmHDUGenerate.c
===================================================================
--- trunk/psModules/src/camera/pmHDUGenerate.c	(revision 14955)
+++ trunk/psModules/src/camera/pmHDUGenerate.c	(revision 15299)
@@ -13,4 +13,6 @@
 #include "pmFPALevel.h"
 #include "pmHDUUtils.h"
+#include "pmConcepts.h"
+#include "pmConceptsStandard.h"
 #include "pmHDUGenerate.h"
 
@@ -169,4 +171,56 @@
     return true;
 }
+
+// Attempt to read CELL.TRIMSEC and CELL.BIASSEC from the cell format if they are specified by VALUE
+static bool readTrimBias(psList *cells // List of cells below the HDU
+    )
+{
+    bool mdok;                          // Status of MD lookup
+    psListIterator *cellsIter = psListIteratorAlloc(cells, PS_LIST_HEAD, false); // Iterator for cells
+    pmCell *cell = NULL;                // Cell from iteration
+    bool allFixed = true;               // We're able to fix all TRIMSEC and BIASSEC
+    while ((cell = psListGetAndIncrement(cellsIter))) {
+        psMetadataItem *trimsecItem = psMetadataLookup(cell->concepts, "CELL.TRIMSEC"); // Item with trimsec
+        if (!trimsecItem || trimsecItem->type != PS_DATA_REGION) {
+            psWarning("CELL.TRIMSEC has not been initialised in cell --- ignored.\n");
+            return false;
+        }
+        psRegion *trimsec = trimsecItem->data.V; // Trim section
+        if (psRegionIsNaN(*trimsec)) {
+            const char *trimsecSource = psMetadataLookupStr(&mdok, cell->config, "CELL.TRIMSEC.SOURCE");
+            if (strcmp(trimsecSource, "VALUE") == 0) {
+
+                const char *trimsecStr = psMetadataLookupStr(&mdok, cell->config, "CELL.TRIMSEC");
+                *trimsec = psRegionFromString(trimsecStr);
+            } else {
+                allFixed = false;
+            }
+        }
+
+        psMetadataItem *biassecItem = psMetadataLookup(cell->concepts, "CELL.BIASSEC"); // Bias sections
+        if (!biassecItem) {
+            psWarning("CELL.BIASSEC has not been initialised in cell --- ignored.\n");
+            return false;
+        }
+        psList *biassecs = biassecItem->data.V;
+        if (biassecs->n != 0) {
+            allFixed = false;
+            continue;
+        }
+
+        const char *biassecSource = psMetadataLookupStr(&mdok, cell->config, "CELL.BIASSEC.SOURCE");
+        if (strcmp(biassecSource, "VALUE") == 0) {
+            const char *biassecStr = psMetadataLookupStr(&mdok, cell->config, "CELL.BIASSEC");
+            psFree(biassecItem->data.V);
+            biassecItem->data.V = p_pmConceptParseRegions(biassecStr);
+        } else {
+            allFixed = false;
+        }
+    }
+    psFree(cellsIter);
+
+    return allFixed;
+}
+
 
 // Generate CELL.TRIMSEC and CELL.BIASSEC for the cells
@@ -341,5 +395,7 @@
     // Get the size of the HDU, either from existing trimsec and biassec, or generate these and try again
     int xSize = 0, ySize = 0;           // Size of HDU
-    if (!sizeHDU(&xSize, &ySize, cells) && !(generateTrimBias(cells) && sizeHDU(&xSize, &ySize, cells))) {
+    if (!sizeHDU(&xSize, &ySize, cells) &&
+        !(readTrimBias(cells) && sizeHDU(&xSize, &ySize, cells)) &&
+        !(generateTrimBias(cells) && sizeHDU(&xSize, &ySize, cells))) {
         psError(PS_ERR_IO, true, "Unable to determine size of HDU!\n");
         return false;
