Index: trunk/ppSkycell/src/ppSkycellCamera.c
===================================================================
--- trunk/ppSkycell/src/ppSkycellCamera.c	(revision 23982)
+++ trunk/ppSkycell/src/ppSkycellCamera.c	(revision 23992)
@@ -9,13 +9,35 @@
 #include "ppSkycell.h"
 
+/// Read list of images
+static psArray *fileList(const char *filename // Filename
+    )
+{
+    psString input = psSlurpFilename(filename);
+    if (!input) {
+        psError(PS_ERR_IO, false, "Unable to read %s", filename);
+        return false;
+    }
+    psArray *inputs = psStringSplitArray(input, "\n", false); // Input filenames
+    psFree(input);
+    if (!inputs || inputs->n == 0) {
+        psError(PS_ERR_IO, false, "Unable to read filenames from %s", filename);
+        psFree(inputs);
+        return NULL;
+    }
+    return inputs;
+}
+
 /// Add a single filename to the arguments as an array, so that it can be used with pmFPAfileBindFromArgs, etc
-static void fileList(const char *file, // The symbolic name for the file
-                     const char *name, // The name of the file
-                     const char *comment, // Description of the file
-                     pmConfig *config // Configuration
+static void fileArguments(const char *file, // The symbolic name for the file
+                          const char *name, // The name of the file
+                          const char *comment, // Description of the file
+                          pmConfig *config // Configuration
     )
 {
     psArray *files = psArrayAlloc(1); // Array with file names
     files->data[0] = psStringCopy(name);
+    if (psMetadataLookup(config->arguments, file)) {
+        psMetadataRemoveKey(config->arguments, file);
+    }
     psMetadataAddArray(config->arguments, PS_LIST_TAIL, file, 0, comment, files);
     psFree(files);
@@ -27,44 +49,55 @@
     )
 {
-    psString input = psSlurpFilename(data->inName);
-    if (!input) {
-        psError(PS_ERR_IO, false, "Unable to read %s", data->inName);
+    psArray *images = fileList(data->imagesName); // Image names
+    if (!images) {
+        psError(psErrorCodeLast(), false, "No images provided.");
         return false;
     }
+    data->numInputs = images->n;
 
-    psArray *inputs = psStringSplitArray(input, "\n", false); // Input filenames
-    psFree(input);
-    if (!inputs || inputs->n == 0) {
-        psError(PS_ERR_IO, false, "Unable to read filenames from %s", data->inName);
-        psFree(inputs);
-        return false;
-    }
-
-    data->numInputs = inputs->n;
-    psMetadataAddArray(config->arguments, PS_LIST_TAIL, "INPUTS", 0, "Input files", inputs);
-    psFree(inputs);
-    psMetadataAddString(config->arguments, PS_LIST_TAIL, "OUTPUT", 0, "Output root", data->outRoot);
-
-    pmFPAfile *inFile = NULL;           // Representative input file
-    for (int i = 0; i < data->numInputs; i++) {
-        bool found = false;             // Found file definition?
-        pmFPAfile *file = pmFPAfileDefineSingleFromArgs(&found, data->config, "PPSKYCELL.INPUT",
-                                                        "INPUTS", i); // Input file
-        if (!file || !found) {
-            psError(psErrorCodeLast(), false, "Unable to define input %d\n", i);
+    psArray *masks = NULL;              // Mask names
+    if (data->masksName) {
+        masks = fileList(data->masksName);
+        if (!masks) {
+            psError(psErrorCodeLast(), false, "No masks provided.");
+            psFree(images);
             return false;
         }
-        if (!inFile) {
-            inFile = file;
+        if (masks->n != data->numInputs) {
+            psError(PS_ERR_BAD_PARAMETER_SIZE, true, "Number of images (%ld) and masks (%ld) do not match",
+                    images->n, masks->n);
+            psFree(images);
+            psFree(masks);
+            return false;
         }
     }
 
-    pmFPAfile *outFile = pmFPAfileDefineFromFile(data->config, inFile, data->bin1, data->bin1,
-                                                 "PPSKYCELL.JPEG1"); // Output file
-    if (!outFile) {
+    psMetadataAddStr(data->config->arguments, PS_LIST_TAIL, "OUTPUT", 0, "Output root", data->outRoot);
+
+    for (int i = 0; i < data->numInputs; i++) {
+        bool status = false;             // Status of file definition
+        fileArguments("IMAGE", images->data[i], "Name of the image", data->config);
+        pmFPAfile *image = pmFPAfileDefineFromArgs(&status, data->config, "PPSKYCELL.IMAGE", "IMAGE"); // File
+        if (!status || !image) {
+            psError(PS_ERR_IO, false, "Failed to build file from PPSKYCELL.IMAGE");
+            // XXX Cleanup
+            return false;
+        }
+
+        if (data->masksName) {
+            fileArguments("MASK", masks->data[i], "Name of the mask", data->config);
+            if (!pmFPAfileBindFromArgs(&status, image, data->config, "PPSKYCELL.MASK", "MASK") || !status) {
+                psError(PS_ERR_IO, false, "Failed to build file from PPSKYCELL.MASK");
+                // XXX Cleanup
+                return false;
+            }
+        }
+    }
+
+    if (!pmFPAfileDefineOutput(data->config, NULL, "PPSKYCELL.JPEG1")) {
         psError(psErrorCodeLast(), false, "Unable to define output.");
         return false;
     }
-    if (!pmFPAfileDefineFromFile(data->config, outFile, data->bin2, data->bin2, "PPSKYCELL.JPEG2")) {
+    if (!pmFPAfileDefineOutput(data->config, NULL, "PPSKYCELL.JPEG2")) {
         psError(psErrorCodeLast(), false, "Unable to define output.");
         return false;
