IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 19441


Ignore:
Timestamp:
Sep 9, 2008, 2:22:19 PM (18 years ago)
Author:
Paul Price
Message:

Masking is more complicated than we support so far. We can't just choose whatever values we want in the MASKS recipe, since masks currently exist that define their own values, and things are set up so that these values are generally copied, rather than proper values set. In the long term, I'd like to revamp the mask system so that each FPA has its own definition of what bits mean what. This is a step towards that, but it's not ready to go yet. I've left the pmConfigMask functions there, but made steps towards putting the masks into the pmFPA; the basic stuff is the same. The FPA-centric mask stuff is #ifdef-ed out, so there should be no functional difference yet.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/psModules/src/config/pmConfigMask.c

    r19155 r19441  
    99#include "pmConfigMask.h"
    1010
    11 
    12 psMaskType pmConfigMaskGet(const char *masks, const pmConfig *config)
    13 {
    14     psAssert(config, "Require configuration");
    15     PS_ASSERT_STRING_NON_EMPTY(masks, 0);
    16 
    17     psMetadata *recipe = psMetadataLookupMetadata(NULL, config->recipes, "MASKS"); // The recipe
    18     if (!recipe) {
    19         psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find MASKS recipe.");
    20         return 0;
    21     }
    22 
     11//////////////////////////////////////////////////////////////////////////////////////////////////////////////
     12// Private functions
     13//////////////////////////////////////////////////////////////////////////////////////////////////////////////
     14
     15static psMaskType maskGet(const psMetadata *source, // Source of masks
     16                          const char *masks // Mask values to get
     17                          )
     18{
    2319    psMaskType mask = 0;                // Mask value, to return
    2420
     
    2723        const char *name = names->data[i]; // Symbolic name of interest
    2824        bool mdok;                      // Status of MD lookup
    29         psMaskType value = psMetadataLookupU8(&mdok, recipe, name);
     25        psMaskType value = psMetadataLookupU8(&mdok, source, name);
    3026        if (!mdok) {
    31             psError(PS_ERR_BAD_PARAMETER_VALUE, false,
    32                     "Unable to find mask value for %s in MASK recipe", name);
     27            psError(PS_ERR_BAD_PARAMETER_VALUE, false, "Unable to find mask value for %s", name);
    3328            psFree(names);
    3429            return 0;
     
    4136}
    4237
    43 bool pmConfigMaskSet(const pmConfig *config, const char *maskName, psMaskType maskValue)
    44 {
    45     psAssert(config, "Require configuration");
    46     PS_ASSERT_STRING_NON_EMPTY(maskName, false);
    47 
    48     psMetadata *recipe = psMetadataLookupMetadata(NULL, config->recipes, "MASKS"); // The recipe
    49     if (!recipe) {
    50         psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find MASKS recipe.");
    51         return false;
    52     }
    53 
    54     psMetadataAddU8 (recipe, PS_LIST_TAIL, maskName, PS_META_REPLACE, "user-defined mask", maskValue);
    55 
    56     return true;
    57 }
    58 
    59 // replace the named masks in the recipe with values in the header:
    60 // replace only the names in the header in the recipe
    61 bool pmConfigMaskReadHeader(pmConfig *config, const psMetadata *header)
    62 {
    63     PS_ASSERT_PTR_NON_NULL(config, false);
    64     PS_ASSERT_METADATA_NON_NULL(header, false);
    65 
    66     bool status = false;
    67 
    68     psMetadata *recipe = psMetadataLookupMetadata(NULL, config->recipes, "MASKS"); // The recipe
    69     if (!recipe) {
    70         psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find MASKS recipe.");
    71         return false;
    72     }
    73 
    74     // MASK.VALUE and MARK.VALUE aren't usually set in the recipe, but may be set in the header: create fake
    75     // versions so that it won't complain later
    76     if (!psMetadataLookup(recipe, "MASK.VALUE")) {
    77         psMetadataAddU8(recipe, PS_LIST_TAIL, "MASK.VALUE", 0, "Bits to mask", 0);
    78     }
    79     if (!psMetadataLookup(recipe, "MARK.VALUE")) {
    80         psMetadataAddU8(recipe, PS_LIST_TAIL, "MARK.VALUE", 0, "Bits for marking", 0);
    81     }
    82 
    83     int nMask = psMetadataLookupS32(&status, header, "MSKNUM");
    84     if (!status) {
    85         if (psMetadataLookupBool(&status, config->camera, "MASK.FORCE")) {
    86             psWarning("No mask values in header.  Assuming MASKS recipe is accurate because of MASK.FORCE");
    87             return true;
    88         }
    89         psError(PS_ERR_UNKNOWN, true, "Unable to find MSKNUM in header.");
    90         return false;
    91     }
    92 
    93     char namekey[80];                   // Keyword name for symbolic name of mask entry
    94     char valuekey[80];                  // Keyword name for value of mask entry
    95     for (int i = 0; i < nMask; i++) {
    96         snprintf(namekey,  64, "MSKNAM%02d", i);
    97         snprintf(valuekey, 64, "MSKVAL%02d", i);
    98 
    99         char *name = psMetadataLookupStr(&status, header, namekey);
    100         if (!status || !name) {
    101             psWarning("Unable to find header keyword %s when parsing mask", namekey);
    102             continue;
    103         }
    104         psU8 bit = psMetadataLookupU8(&status, header, valuekey);
    105         if (!status) {
    106             psWarning("Unable to find header keyword %s when parsing mask", namekey);
    107             continue;
    108         }
    109 
    110         // XXX validate that bit is a 2^n value?
    111 
    112         psString nameAlready = NULL;    // Name of key with ".ALREADY" added
    113         psStringAppend(&nameAlready, "%s.ALREADY", name);
    114         bool already = psMetadataLookupBool(&status, recipe, nameAlready); // Already read this one?
    115 
    116         psMetadataItem *item = psMetadataLookup(recipe, name); // Item in recipe with current value
    117         if (item && item->type != PS_TYPE_MASK) {
    118             psWarning("Mask recipe entry is not of a mask type (%x)", item->type);
    119             item->type = PS_TYPE_MASK;
    120         }
    121 
    122         if (already) {
    123             if (item && item->data.U8 != bit) {
    124                 psWarning("New mask recipe entry doesn't match previously loaded entry: %x vs %x",
    125                           bit, item->data.U8);
     38// maskSetValues examine named mask values and set the bits for maskValue and markValue.
     39// Ensures that the below-named bad mask values are set, and calculates the mask value to catch them all
     40// Ensure that the below-named other mask values are set (to 0x00 if necessary)
     41
     42// List of mask names for "bad" (i.e., mask me please) pixels
     43static const char *badMaskNames[] = { "DETECTOR", // Something is wrong with the detector
     44                                      "DARK", // Pixel doesn't dark-subtract properly
     45                                      "FLAT", // Pixel doesn't flat-field properly
     46                                      "BLANK", // Pixel doesn't contain valid data
     47                                      "RANGE",// Pixel is out-of-range of linearity
     48                                      "SAT",  // Pixel is saturated
     49                                      "LOW",  // Pixel is low
     50                                      "CONV", // Pixel is bad after convolution with a bad pixel
     51                                      "CR",   // Pixel contains a cosmic ray
     52                                      "GHOST",// Pixel contains an optical ghost
     53                                      NULL // End marker
     54};
     55// Fallback names in case a bad mask name is not defined
     56static const char *fallbackMaskNames[] = { NULL, // DETECTOR
     57                                           "DETECTOR", // DARK
     58                                           "DETECTOR", // FLAT
     59                                           "DETECTOR", // BLANK
     60                                           NULL, // RANGE
     61                                           "RANGE", // SAT
     62                                           "RANGE", // LOW
     63                                           NULL, // CONV
     64                                           NULL, // CR
     65                                           NULL, // GHOST
     66};
     67// Default values in case a bad mask name and its fallback is not defined
     68static const psMaskType defaultMask[] = { 0x00, // DETECTOR
     69                                          0x00, // DARK
     70                                          0x01, // FLAT
     71                                          0x01, // BLANK
     72                                          0x00, // RANGE
     73                                          0x01, // SAT
     74                                          0x01, // LOW
     75                                          0x01, // CONV
     76                                          0x00, // CR
     77                                          0x00  // GHOST
     78};
     79// Other mask names to ensure exist; these shouldn't be combined in the MASK.VALUE
     80static const char *otherMaskNames[] = { "POOR", // Pixel is poor after convolution with a bad pixel
     81                                        NULL // End marker
     82};
     83
     84static bool maskSetValues(psMaskType *outMaskValue, // Value of MASK.VALUE, returned
     85                          psMaskType *outMarkValue, // Value of MARK.VALUE, returned
     86                          psMetadata *source  // Source of mask bits
     87                          )
     88{
     89    PS_ASSERT_METADATA_NON_NULL(source, false);
     90
     91    // Ensure all the bad mask names exist, and set the value to catch all bad pixels
     92    psMaskType maskValue = 0;           // Value to mask to catch all the bad pixels
     93    for (int i = 0; badMaskNames[i]; i++) {
     94        const char *name = badMaskNames[i]; // Name for mask
     95        const char *fallback = fallbackMaskNames[i]; // Fallback for mask
     96
     97        bool mdok;                      // Status of MD lookup
     98        psMaskType value = psMetadataLookupU8(&mdok, source, name); // Value of mask
     99        if (!value) {
     100            if (fallback) {
     101                value = psMetadataLookupU8(&mdok, source, fallback);
    126102            }
     103            if (!value) {
     104                value = defaultMask[i];
     105            }
     106            psMetadataAddU8(source, PS_LIST_TAIL, name, PS_META_REPLACE, NULL, value);
     107        }
     108        maskValue |= value;
     109    }
     110
     111    // Ensure all the other mask names exist
     112    for (int i = 0; otherMaskNames[i]; i++) {
     113        const char *name = otherMaskNames[i]; // Name for mask
     114        bool mdok;                      // Status of MD lookup
     115        psMaskType value = psMetadataLookupU8(&mdok, source, name); // Value of mask
     116        if (!value) {
     117            psMetadataAddU8(source, PS_LIST_TAIL, name, PS_META_REPLACE, NULL, 0x00);
     118        }
     119    }
     120
     121    // search for an unset bit to use for MARK:
     122    psMaskType markValue = 0x80;
     123
     124    int nBits = sizeof(psMaskType) * 8;
     125    for (int i = 0; !markValue && (i < nBits); i++) {
     126        if (maskValue & markValue) {
     127            markValue >>= 1;
    127128        } else {
    128             psMetadataAddBool(recipe, PS_LIST_TAIL, nameAlready, 0, "Already read this mask value", true);
    129         }
    130 
    131         if (!item) {
    132             psWarning("Mask recipe entry %s not in recipe\n", name);
    133             psMetadataAddU8(recipe, PS_LIST_TAIL, name, 0, "Bitmask bit value", bit);
    134         } else {
    135             item->data.U8 = bit;
    136         }
    137 
    138         psFree(nameAlready);
    139     }
    140 
     129            markValue = markValue;
     130        }
     131    }
     132    if (!markValue) {
     133        psError (PS_ERR_UNKNOWN, true, "Unable to define the MARK bit mask: all bits taken!");
     134        return false;
     135    }
     136
     137    // update the list with the results
     138    psMetadataAddU8(source, PS_LIST_TAIL, "MASK.VALUE", PS_META_REPLACE, NULL, maskValue);
     139    psMetadataAddU8(source, PS_LIST_TAIL, "MARK.VALUE", PS_META_REPLACE, NULL, markValue);
     140
     141    if (outMaskValue) {
     142        *outMaskValue = maskValue;
     143    }
     144    if (outMarkValue) {
     145        *outMarkValue = markValue;
     146    }
    141147
    142148    return true;
     
    162168}
    163169
    164 
    165 // write the named mask bits to the header
    166 bool pmConfigMaskWriteHeader(const pmConfig *config, psMetadata *header)
    167 {
     170//////////////////////////////////////////////////////////////////////////////////////////////////////////////
     171// FPA version of mask functions.  These are not ready to go yet.
     172//////////////////////////////////////////////////////////////////////////////////////////////////////////////
     173
     174#if 0
     175bool pmFPAMaskSetValues(psMaskType *outMaskValue, psMaskType *outMarkValue, pmFPA *fpa)
     176{
     177    PS_ASSERT_PTR_NON_NULL(fpa, false);
     178
     179    return maskSetValues(outMaskValue, outMarkValue, fpa->masks);
     180}
     181
     182psMaskType pmFPAMaskGet(const pmFPA *fpa, const char *masks, const pmConfig *config)
     183{
     184    PS_ASSERT_PTR_NON_NULL(fpa, 0);
     185    PS_ASSERT_STRING_NON_EMPTY(masks, 0);
     186    PS_ASSERT_PTR_NON_NULL(config, 0);
     187
     188    if (fpa->masks) {
     189        return maskGet(fpa->masks, masks);
     190    }
     191    return pmConfigMaskGet(masks, config);
     192}
     193
     194bool pmFPAMaskSet(pmFPA *fpa, const char *maskName, psMaskType maskValue)
     195{
     196    PS_ASSERT_PTR_NON_NULL(fpa, 0);
     197    PS_ASSERT_STRING_NON_EMPTY(maskName, false);
     198
     199    if (!fpa->masks) {
     200        fpa->masks = psMetadataAlloc();
     201    }
     202    return psMetadataAddU8(fpa->masks, PS_LIST_TAIL, maskName, PS_META_REPLACE, NULL, maskValue);
     203}
     204
     205bool pmFPAMaskReadHeader(pmFPA *fpa, const psMetadata *header, pmConfig *config)
     206{
     207    PS_ASSERT_PTR_NON_NULL(fpa, false);
     208    PS_ASSERT_METADATA_NON_NULL(header, false);
    168209    PS_ASSERT_PTR_NON_NULL(config, false);
     210
     211    if (!fpa->masks) {
     212        fpa->masks = psMetadataAlloc();
     213    }
     214
     215    bool mdok;                          // Status of MD lookup
     216    int numMask = psMetadataLookupS32(&mdok, header, "MSKNUM"); // Number of mask values in header
     217    if (!mdok) {
     218        if (psMetadataLookupBool(&mdok, config->camera, "MASK.FORCE")) {
     219            psWarning("No mask values in header.  Assuming MASKS recipe is accurate because of MASK.FORCE");
     220            numMask = 0;
     221        } else {
     222            psError(PS_ERR_UNKNOWN, true, "Unable to find MSKNUM in header.");
     223            return false;
     224        }
     225    }
     226
     227    char namekey[80];                   // Keyword name for symbolic name of mask entry
     228    char valuekey[80];                  // Keyword name for value of mask entry
     229    for (int i = 0; i < numMask; i++) {
     230        snprintf(namekey,  64, "MSKNAM%02d", i);
     231        snprintf(valuekey, 64, "MSKVAL%02d", i);
     232
     233        char *name = psMetadataLookupStr(&mdok, header, namekey);
     234        if (!mdok || !name) {
     235            psWarning("Unable to find header keyword %s when parsing mask", namekey);
     236            continue;
     237        }
     238        psU8 bit = psMetadataLookupU8(&mdok, header, valuekey);
     239        if (!mdok) {
     240            psWarning("Unable to find header keyword %s when parsing mask", namekey);
     241            continue;
     242        }
     243
     244        // XXX validate that bit is a 2^n value?
     245
     246        psMetadataItem *item = psMetadataLookup(fpa->masks, name); // Item in recipe with current value
     247        if (item) {
     248            psAssert(item->type == PS_TYPE_MASK, "Mask entry %s is not of a mask type (%x)",
     249                     name, item->type);
     250            if (item->data.PS_TYPE_MASK_DATA != bit) {
     251                psWarning("New mask entry %s doesn't match previously loaded entry: %x vs %x",
     252                          name, bit, item->data.PS_TYPE_MASK_DATA);
     253            }
     254        } else {
     255            psMetadataAddU8(fpa->masks, PS_LIST_TAIL, name, 0, NULL, bit);
     256        }
     257    }
     258
     259    // Now copy everything else from the recipe
     260    psMetadata *recipe = psMetadataLookupMetadata(NULL, config->recipes, "MASKS"); // The recipe
     261    if (!recipe) {
     262        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find MASKS recipe.");
     263        return false;
     264    }
     265
     266    psMetadataIterator *iter = psMetadataIteratorAlloc(recipe, PS_LIST_HEAD, NULL); // Iterator
     267    psMetadataItem *item;               // Item from iteration
     268    while ((item = psMetadataGetAndIncrement(iter))) {
     269        if (item->type != PS_TYPE_MASK) {
     270            psWarning("Recipe mask entry %s is not of a mask type (%x)", item->name, item->type);
     271            continue;
     272        }
     273        if (!psMetadataLookup(fpa->masks, item->name)) {
     274            psMetadataAddU8(fpa->masks, PS_LIST_TAIL, item->name, 0, item->comment,
     275                            item->data.PS_TYPE_MASK_DATA);
     276        }
     277    }
     278    psFree(iter);
     279
     280    return true;
     281}
     282
     283
     284bool pmFPAMaskWriteHeader(psMetadata *header, const pmFPA *fpa)
     285{
    169286    PS_ASSERT_METADATA_NON_NULL(header, false);
     287    PS_ASSERT_PTR_NON_NULL(fpa, false);
    170288
    171289    maskRemoveHeader(header, "MSKNAM");
     
    175293    }
    176294
     295    char namekey[80], valuekey[80];     // Mask name and mask value header keywords
     296    int numMask = 0;                    // Number of mask entries
     297
     298    psMetadataIterator *iter = psMetadataIteratorAlloc(fpa->masks, PS_LIST_HEAD, NULL); // Iterator
     299    psMetadataItem *item;               // Item from iteration
     300    while ((item = psMetadataGetAndIncrement(iter))) {
     301        if (item->type != PS_TYPE_MASK) {
     302            psWarning("mask recipe entry %s is not of a mask type (%x)", item->name, item->type);
     303            continue;
     304        }
     305
     306        snprintf(namekey,  64, "MSKNAM%02d", numMask);
     307        snprintf(valuekey, 64, "MSKVAL%02d", numMask);
     308
     309        psMetadataAddStr(header, PS_LIST_TAIL, namekey, 0, "Bitmask bit name", item->name);
     310        psMetadataAddU8(header, PS_LIST_TAIL, valuekey, 0, "Bitmask bit value", item->data.PS_TYPE_MASK_DATA);
     311        numMask++;
     312    }
     313    psFree(iter);
     314
     315    return psMetadataAddS32(header, PS_LIST_TAIL, "MSKNUM", 0, "Number of named mask entries", numMask);
     316}
     317
     318#endif
     319
     320
     321psMaskType pmConfigMaskGet(const char *masks, const pmConfig *config)
     322{
     323    psAssert(config, "Require configuration");
     324    PS_ASSERT_STRING_NON_EMPTY(masks, 0);
     325
     326    psMetadata *recipe = psMetadataLookupMetadata(NULL, config->recipes, "MASKS"); // The recipe
     327    if (!recipe) {
     328        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find MASKS recipe.");
     329        return 0;
     330    }
     331    return maskGet(recipe, masks);
     332}
     333
     334
     335bool pmConfigMaskSet(const pmConfig *config, const char *maskName, psMaskType maskValue)
     336{
     337    psAssert(config, "Require configuration");
     338    PS_ASSERT_STRING_NON_EMPTY(maskName, false);
     339
     340    psMetadata *recipe = psMetadataLookupMetadata(NULL, config->recipes, "MASKS"); // The recipe
     341    if (!recipe) {
     342        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find MASKS recipe.");
     343        return false;
     344    }
     345
     346    return psMetadataAddU8(recipe, PS_LIST_TAIL, maskName, PS_META_REPLACE, NULL, maskValue);
     347}
     348
     349
     350// replace the named masks in the recipe with values in the header:
     351// replace only the names in the header in the recipe
     352bool pmConfigMaskReadHeader(pmConfig *config, const psMetadata *header)
     353{
     354    PS_ASSERT_PTR_NON_NULL(config, false);
     355    PS_ASSERT_METADATA_NON_NULL(header, false);
     356
     357    bool status = false;
     358
     359    psMetadata *recipe = psMetadataLookupMetadata(NULL, config->recipes, "MASKS"); // The recipe
     360    if (!recipe) {
     361        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find MASKS recipe.");
     362        return false;
     363    }
     364
     365    // MASK.VALUE and MARK.VALUE aren't usually set in the recipe, but may be set in the header: create fake
     366    // versions so that it won't complain later
     367    if (!psMetadataLookup(recipe, "MASK.VALUE")) {
     368        psMetadataAddU8(recipe, PS_LIST_TAIL, "MASK.VALUE", 0, "Bits to mask", 0);
     369    }
     370    if (!psMetadataLookup(recipe, "MARK.VALUE")) {
     371        psMetadataAddU8(recipe, PS_LIST_TAIL, "MARK.VALUE", 0, "Bits for marking", 0);
     372    }
     373
     374    int nMask = psMetadataLookupS32(&status, header, "MSKNUM");
     375    if (!status) {
     376        if (psMetadataLookupBool(&status, config->camera, "MASK.FORCE")) {
     377            psWarning("No mask values in header.  Assuming MASKS recipe is accurate because of MASK.FORCE");
     378            return true;
     379        }
     380        psError(PS_ERR_UNKNOWN, true, "Unable to find MSKNUM in header.");
     381        return false;
     382    }
     383
     384    char namekey[80];                   // Keyword name for symbolic name of mask entry
     385    char valuekey[80];                  // Keyword name for value of mask entry
     386    for (int i = 0; i < nMask; i++) {
     387        snprintf(namekey,  64, "MSKNAM%02d", i);
     388        snprintf(valuekey, 64, "MSKVAL%02d", i);
     389
     390        char *name = psMetadataLookupStr(&status, header, namekey);
     391        if (!status || !name) {
     392            psWarning("Unable to find header keyword %s when parsing mask", namekey);
     393            continue;
     394        }
     395        psU8 bit = psMetadataLookupU8(&status, header, valuekey);
     396        if (!status) {
     397            psWarning("Unable to find header keyword %s when parsing mask", namekey);
     398            continue;
     399        }
     400
     401        // XXX validate that bit is a 2^n value?
     402
     403        psString nameAlready = NULL;    // Name of key with ".ALREADY" added
     404        psStringAppend(&nameAlready, "%s.ALREADY", name);
     405        bool already = psMetadataLookupBool(&status, recipe, nameAlready); // Already read this one?
     406
     407        psMetadataItem *item = psMetadataLookup(recipe, name); // Item in recipe with current value
     408        if (item && item->type != PS_TYPE_MASK) {
     409            psWarning("Mask recipe entry is not of a mask type (%x)", item->type);
     410            item->type = PS_TYPE_MASK;
     411        }
     412
     413        if (already) {
     414            if (item && item->data.U8 != bit) {
     415                psWarning("New mask recipe entry doesn't match previously loaded entry: %x vs %x",
     416                          bit, item->data.U8);
     417            }
     418        } else {
     419            psMetadataAddBool(recipe, PS_LIST_TAIL, nameAlready, 0, "Already read this mask value", true);
     420        }
     421
     422        if (!item) {
     423            psWarning("Mask recipe entry %s not in recipe\n", name);
     424            psMetadataAddU8(recipe, PS_LIST_TAIL, name, 0, "Bitmask bit value", bit);
     425        } else {
     426            item->data.U8 = bit;
     427        }
     428
     429        psFree(nameAlready);
     430    }
     431
     432
     433    return true;
     434}
     435
     436
     437
     438// write the named mask bits to the header
     439bool pmConfigMaskWriteHeader(const pmConfig *config, psMetadata *header)
     440{
     441    PS_ASSERT_PTR_NON_NULL(config, false);
     442    PS_ASSERT_METADATA_NON_NULL(header, false);
     443
     444    maskRemoveHeader(header, "MSKNAM");
     445    maskRemoveHeader(header, "MSKVAL");
     446    if (psMetadataLookup(header, "MSKNUM")) {
     447        psMetadataRemoveKey(header, "MSKNUM");
     448    }
     449
    177450    char namekey[80];
    178451    char valuekey[80];
     
    211484}
    212485
    213 // examine named mask values in mask recipe and set the bits for maskValue and markValue
    214 // this function sets an appropriate value for the following required named mask concepts:
    215 // FLAT (used to mark out-of-range corrections in the flat-fielding)
    216 // BLANK (used to mark non-existent pixels)
    217 // SAT (used to mark pixels with values out-of-range on the high end)
    218 // BAD (used to mark pixels with values out-of-range on the low end)
    219 // If there is no explicit value for the above, the 'DETECTOR' and 'RANGE' bits are used
    220 // If these latter do not exist, the value 0x01 is used.
    221 // The values actually used for these names are written back to the config file
     486
    222487bool pmConfigMaskSetBits(psMaskType *outMaskValue, psMaskType *outMarkValue, const pmConfig *config)
    223488{
    224489    PS_ASSERT_PTR_NON_NULL(config, false);
    225490
    226     psMaskType maskValue = 0;
    227 
    228     // mask for generic detector defect
    229     psMaskType detectorMask = pmConfigMaskGet("DETECTOR", config);
    230     maskValue |= detectorMask;
    231 
    232     // mask for dark structures
    233     psMaskType darkMask = pmConfigMaskGet("DARK", config);
    234     maskValue |= darkMask;
    235 
    236     // mask for non-linear flat regions (default to DETECTOR if not defined)
    237     psMaskType flatMask = pmConfigMaskGet("FLAT", config);
    238     if (!flatMask) {
    239         flatMask = detectorMask;
    240         pmConfigMaskSet (config, "FLAT", flatMask);
    241     }
    242     if (!flatMask) {
    243         flatMask = 0x01;
    244         pmConfigMaskSet (config, "FLAT", flatMask);
    245     }
    246     maskValue |= flatMask;
    247 
    248     // mask for non-existent data  (default to DETECTOR if not defined)
    249     psMaskType blankMask = pmConfigMaskGet("BLANK", config);
    250     if (!blankMask) {
    251         blankMask = detectorMask;
    252         pmConfigMaskSet (config, "BLANK", blankMask);
    253     }
    254     if (!blankMask) {
    255         blankMask = 0x01;
    256         pmConfigMaskSet (config, "BLANK", blankMask);
    257     }
    258     maskValue |= blankMask;
    259 
    260     // mask for generic data range errors
    261     psMaskType rangeMask = pmConfigMaskGet("RANGE", config);
    262     maskValue |= rangeMask;
    263 
    264     // mask for saturated data  (default to RANGE if not defined)
    265     psMaskType satMask = pmConfigMaskGet("SAT", config);
    266     if (!satMask) {
    267         satMask = rangeMask;
    268         pmConfigMaskSet (config, "SAT", satMask);
    269     }
    270     if (!satMask) {
    271         satMask = 0x01;
    272         pmConfigMaskSet (config, "SAT", satMask);
    273     }
    274     maskValue |= satMask;
    275 
    276     // mask for below-range data  (default to RANGE if not defined)
    277     psMaskType badMask = pmConfigMaskGet("BAD", config);
    278     if (!badMask) {
    279         badMask = rangeMask;
    280         pmConfigMaskSet (config, "BAD", badMask);
    281     }
    282     if (!badMask) {
    283         badMask = 0x01;
    284         pmConfigMaskSet (config, "BAD", badMask);
    285     }
    286     maskValue |= badMask;
    287 
    288     // XXX not sure what to do with these
    289     psMaskType crMask = pmConfigMaskGet("CR", config);
    290     maskValue |= crMask;
    291 
    292     psMaskType ghostMask = pmConfigMaskGet("GHOST", config);
    293     maskValue |= ghostMask;
    294 
    295     // search for an unset bit to use for MARK:
    296     psMaskType markValue = 0x80;
    297 
    298     int nBits = sizeof(psMaskType) * 8;
    299     for (int i = 0; !markValue && (i < nBits); i++) {
    300         if (maskValue & markValue) {
    301             markValue >>= 1;
    302         } else {
    303             markValue = markValue;
    304         }
    305     }
    306     if (!markValue) {
    307         psError (PS_ERR_UNKNOWN, true, "Unable to define the MARK bit mask: all bits taken!");
    308         return false;
    309     }
    310 
    311 
    312     // update the config table
    313     pmConfigMaskSet(config, "MASK.VALUE", maskValue);
    314     pmConfigMaskSet(config, "MARK.VALUE", markValue);
    315 
    316     if (outMaskValue) {
    317         *outMaskValue = maskValue;
    318     }
    319     if (outMarkValue) {
    320         *outMarkValue = markValue;
    321     }
    322 
    323     return true;
    324 }
     491    psMetadata *recipe = psMetadataLookupMetadata(NULL, config->recipes, "MASKS"); // The recipe
     492    if (!recipe) {
     493        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find MASKS recipe.");
     494        return false;
     495    }
     496
     497    return maskSetValues(outMaskValue, outMarkValue, recipe);
     498}
Note: See TracChangeset for help on using the changeset viewer.