Changeset 21143
- Timestamp:
- Jan 19, 2009, 4:56:51 PM (17 years ago)
- Location:
- branches/eam_branch_20081230/psModules/src/config
- Files:
-
- 2 edited
-
pmConfigMask.c (modified) (9 diffs)
-
pmConfigMask.h (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
branches/eam_branch_20081230/psModules/src/config/pmConfigMask.c
r21130 r21143 9 9 #include "pmConfigMask.h" 10 10 11 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// 12 // Private functions 13 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// 14 15 // maskSetValues examine named mask values and set the bits for maskValue and markValue. 16 // Ensures that the below-named bad mask values are set, and calculates the mask value to catch them all 17 // Ensure that the below-named other mask values are set (to 0x00 if necessary) 18 19 // List of mask names for "bad" (i.e., mask me please) pixels 20 static const char *badMaskNames[] = { "DETECTOR", // Something is wrong with the detector 21 "DARK", // Pixel doesn't dark-subtract properly 22 "FLAT", // Pixel doesn't flat-field properly 23 "BLANK", // Pixel doesn't contain valid data 24 "RANGE",// Pixel is out-of-range of linearity 25 "SAT", // Pixel is saturated 26 // "LOW", // Pixel is low 27 // "CONV", // Pixel is bad after convolution with a bad pixel 28 "BAD", // Pixel is low 29 "BAD.WARP", // Pixel is bad after convolution with a bad pixel 30 "CR", // Pixel contains a cosmic ray 31 "GHOST",// Pixel contains an optical ghost 32 NULL // End marker 11 static pmConfigMaskInfo masks[] = { 12 { "DETECTOR", NULL, 0x00, true }, // Something is wrong with the detector 13 { "DARK", "DETECTOR", 0x00, true }, // Pixel doesn't dark-subtract properly 14 { "FLAT", "DETECTOR", 0x01, true }, // Pixel doesn't flat-field properly 15 { "BLANK", "DETECTOR", 0x01, true }, // Pixel doesn't contain valid data 16 { "RANGE", NULL, 0x00, true }, // Pixel is out-of-range of linearity 17 { "SAT", "RANGE", 0x01, true }, // Pixel is saturated 18 { "BAD", "RANGE", 0x01, true }, // Pixel is low 19 { "BAD.WARP", NULL, 0x01, true }, // Pixel is bad after convolution with a bad pixel 20 { "CR", NULL, 0x00, true }, // Pixel contains a cosmic ray 21 { "GHOST", NULL, 0x00, true }, // Pixel contains an optical ghost 22 { "POOR.WARP", NULL, 0x00, false }, // Pixel is poor after convolution with a bad pixel 23 // "LOW" Pixel is low 24 // "CONV" Pixel is bad after convolution with a bad pixel 33 25 }; 34 // Fallback names in case a bad mask name is not defined 35 static const char *fallbackMaskNames[] = { NULL, // DETECTOR 36 "DETECTOR", // DARK 37 "DETECTOR", // FLAT 38 "DETECTOR", // BLANK 39 NULL, // RANGE 40 "RANGE", // SAT 41 "RANGE", // LOW 42 NULL, // CONV 43 NULL, // CR 44 NULL, // GHOST 45 }; 46 // Default values in case a bad mask name and its fallback is not defined 47 static const psImageMaskType defaultMask[] = { 0x00, // DETECTOR 48 0x00, // DARK 49 0x01, // FLAT 50 0x01, // BLANK 51 0x00, // RANGE 52 0x01, // SAT 53 0x01, // LOW 54 0x01, // CONV 55 0x00, // CR 56 0x00 // GHOST 57 }; 58 // Other mask names to ensure exist; these shouldn't be combined in the MASK.VALUE 59 static const char *otherMaskNames[] = { // "POOR", // Pixel is poor after convolution with a bad pixel 60 "POOR.WARP", // Pixel is poor after convolution with a bad pixel 61 NULL // End marker 62 }; 63 64 static bool maskSetValues(psImageMaskType *outMaskValue, // Value of MASK.VALUE, returned 65 psImageMaskType *outMarkValue, // Value of MARK.VALUE, returned 66 psMetadata *source // Source of mask bits 67 ) 26 27 // The functions in this file do not force the recipe or header values to be stored as the same 28 // type as psImageMaskType : they only check that the given values will fit in the space 29 // provided by psImageMaskType. This should allow some backwards compatibility (old 8-bit 30 // masks will work with a 16-bit system), but will catch unhandled conflicts (trying to fit 16 31 // bits in 8-bits of space). 32 33 // XXX this file does not have psError vs psWarning worked out correctly. some of the 34 // failure modes should result in errors, not just warnings. 35 36 // pmConfigMaskSetInMetadata examines named mask values and set the bits for maskValue and 37 // markValue. Ensures that the below-named mask values are set, and calculates the mask value 38 // to catch all of the mask values marked as 'bad'. Supplies the fallback name if the primary 39 // name is not found, or the default values if the fallback name is not found. 40 41 bool pmConfigMaskSetInMetadata(psImageMaskType *outMaskValue, // Value of MASK.VALUE, returned 42 psImageMaskType *outMarkValue, // Value of MARK.VALUE, returned 43 psMetadata *source // Source of mask bits 44 ) 68 45 { 69 46 PS_ASSERT_METADATA_NON_NULL(source, false); 70 47 71 48 // Ensure all the bad mask names exist, and set the value to catch all bad pixels 72 49 psImageMaskType maskValue = 0; // Value to mask to catch all the bad pixels 73 for (int i = 0; badMaskNames[i]; i++) { 74 const char *name = badMaskNames[i]; // Name for mask 75 const char *fallback = fallbackMaskNames[i]; // Fallback for mask 76 50 psImageMaskType allMasks = 0; // Value to mask to catch all masked bits (to set MARK) 51 52 int nMasks = sizeof (masks) / sizeof (pmConfigMaskInfo); 53 54 for (int i = 0; i < nMasks; i++) { 77 55 bool mdok; // Status of MD lookup 78 psImageMaskType value = psMetadataLookupImageMask(&mdok, source, name); // Value of mask 56 psImageMaskType value = psMetadataLookupImageMaskFromGeneric(&mdok, source, masks[i].badMaskName); // Value of mask 57 if (!mdok) { 58 psWarning ("problem with mask value %s\n", masks[i].badMaskName); 59 } 60 79 61 if (!value) { 80 if (fallback) { 81 value = psMetadataLookupImageMask(&mdok, source, fallback); 82 } 83 if (!value) { 84 value = defaultMask[i]; 85 } 86 psMetadataAddImageMask(source, PS_LIST_TAIL, name, PS_META_REPLACE, NULL, value); 87 } 88 maskValue |= value; 89 } 90 91 // Ensure all the other mask names exist 92 for (int i = 0; otherMaskNames[i]; i++) { 93 const char *name = otherMaskNames[i]; // Name for mask 94 bool mdok; // Status of MD lookup 95 psImageMaskType value = psMetadataLookupImageMask(&mdok, source, name); // Value of mask 96 if (!value) { 97 psMetadataAddImageMask(source, PS_LIST_TAIL, name, PS_META_REPLACE, NULL, 0x00); 98 } 62 if (masks[i].fallbackName) { 63 value = psMetadataLookupImageMaskFromGeneric(&mdok, source, masks[i].fallbackName); 64 } 65 if (!value) { 66 value = masks[i].defaultMaskValue; 67 } 68 psMetadataAddImageMask(source, PS_LIST_TAIL, masks[i].badMaskName, PS_META_REPLACE, NULL, value); 69 } 70 if (masks[i].isBad) { 71 maskValue |= value; 72 } 73 allMasks |= value; 99 74 } 100 75 … … 105 80 int nBits = sizeof(psImageMaskType) * 8; 106 81 for (int i = 0; !markValue && (i < nBits); i++) { 107 if ( maskValue& markTrial) {82 if (allMasks & markTrial) { 108 83 markTrial <<= 1; 109 84 } else { … … 131 106 132 107 // Get a mask value by name(s) 133 static psImageMaskType maskGet(psMetadata *source, // Source of masks134 const char *masks // Mask values to get135 )108 psImageMaskType pmConfigMaskGetFromMetadata(psMetadata *source, // Source of masks 109 const char *masks // Mask values to get 110 ) 136 111 { 137 112 psImageMaskType mask = 0; // Mask value, to return … … 141 116 const char *name = names->data[i]; // Symbolic name of interest 142 117 bool mdok; // Status of MD lookup 143 psImageMaskType value = psMetadataLookupImageMask (&mdok, source, name);118 psImageMaskType value = psMetadataLookupImageMaskFromGeneric(&mdok, source, name); 144 119 if (!mdok) { 145 120 // Try and generate the value if we can 146 121 if (strcmp(name, "MASK.VALUE") == 0 || strcmp(name, "MARK.VALUE") == 0) { 147 if (! maskSetValues(NULL, NULL, source)) {122 if (!pmConfigMaskSetInMetadata(NULL, NULL, source)) { 148 123 psError(PS_ERR_UNKNOWN, false, "Unable to set mask bits."); 149 124 return 0; 150 125 } 151 value = psMetadataLookupImageMask (&mdok, source, name);126 value = psMetadataLookupImageMaskFromGeneric(&mdok, source, name); 152 127 psAssert(mdok, "Should have generated mask value"); 153 128 } else { … … 164 139 } 165 140 141 // lookup an image mask value by name from a psMetadata, without requiring the entry to 142 // be of type psImageMaskType, but verifying that it will fit in psImageMaskType 143 psImageMaskType psMetadataLookupImageMaskFromGeneric (bool *status, const psMetadata *md, const char *name) { 144 145 *status = true; 146 147 // select the mask bit name from the header 148 psMetadataItem *item = psMetadataLookup (md, name); 149 if (!item) { 150 psWarning("Unable to find header keyword %s when parsing mask", name); 151 *status = false; 152 return 0; 153 } 154 155 // the value may be any of the U8, U16, U32, U64 types : accept the value regardless of type size 156 psU64 fullValue = 0; 157 switch (item->type) { 158 case PS_DATA_U8: 159 fullValue = item->data.U8; 160 break; 161 case PS_DATA_U16: 162 fullValue = item->data.U16; 163 break; 164 case PS_DATA_U32: 165 fullValue = item->data.U32; 166 break; 167 case PS_DATA_U64: 168 fullValue = item->data.U64; 169 break; 170 // XXX we could code this to accept Snn values, but they should not normally be used for masks 171 default: 172 psWarning("Mask entry %s in metadata is not of a mask type", name); 173 *status = false; 174 return 0; 175 } 176 177 // will the incoming value fit within the current image mask type? 178 if (fullValue > PS_MAX_IMAGE_MASK_TYPE) { 179 psWarning("Mask entry %s in metadata is larger than allowed by the psImageMaskType", name); 180 *status = false; 181 return 0; 182 } 183 psImageMaskType value = fullValue; 184 // XXX validate that value is a 2^n value? 185 186 return value; 187 } 188 166 189 // Remove from the header keywords starting with the provided string 167 static int maskRemoveHeader(psMetadata *header, // Header from which to remove keywords168 const char *start // Remove keywords that start with this string169 )190 int pmConfigMaskRemoveHeaderKeywords(psMetadata *header, // Header from which to remove keywords 191 const char *start // Remove keywords that start with this string 192 ) 170 193 { 171 194 psString regex = NULL; // Regular expression for keywords … … 183 206 } 184 207 208 // look up the named mask value(s) from the MASKS recipe in the config system 209 psImageMaskType pmConfigMaskGet(const char *masks, const pmConfig *config) 210 { 211 psAssert(config, "Require configuration"); 212 PS_ASSERT_STRING_NON_EMPTY(masks, 0); 213 214 bool mdok; // Status of MD lookup 215 psMetadata *recipe = psMetadataLookupMetadata(&mdok, config->recipes, "MASKS"); // The recipe 216 if (!recipe) { 217 psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find MASKS recipe."); 218 return 0; 219 } 220 221 psImageMaskType mask = pmConfigMaskGetFromMetadata (recipe, masks); 222 return mask; 223 } 224 225 bool pmConfigMaskSet(const pmConfig *config, const char *maskName, psImageMaskType maskValue) 226 { 227 psAssert(config, "Require configuration"); 228 PS_ASSERT_STRING_NON_EMPTY(maskName, false); 229 230 psMetadata *recipe = psMetadataLookupMetadata(NULL, config->recipes, "MASKS"); // The recipe 231 if (!recipe) { 232 psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find MASKS recipe."); 233 return false; 234 } 235 236 bool status = psMetadataAddImageMask(recipe, PS_LIST_TAIL, maskName, PS_META_REPLACE, NULL, maskValue); 237 return status; 238 } 239 240 241 // replace the named masks in the recipe with values in the header: 242 // replace only the names in the header in the recipe 243 bool pmConfigMaskReadHeader(pmConfig *config, const psMetadata *header) 244 { 245 PS_ASSERT_PTR_NON_NULL(config, false); 246 PS_ASSERT_METADATA_NON_NULL(header, false); 247 248 bool status = false; 249 250 psMetadata *recipe = psMetadataLookupMetadata(NULL, config->recipes, "MASKS"); // The recipe 251 if (!recipe) { 252 psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find MASKS recipe."); 253 return false; 254 } 255 256 // MASK.VALUE and MARK.VALUE aren't usually set in the recipe, but may be set in the header: create fake 257 // versions so that it won't complain later 258 if (!psMetadataLookup(recipe, "MASK.VALUE")) { 259 psMetadataAddImageMask(recipe, PS_LIST_TAIL, "MASK.VALUE", 0, "Bits to mask", 0); 260 } 261 if (!psMetadataLookup(recipe, "MARK.VALUE")) { 262 psMetadataAddImageMask(recipe, PS_LIST_TAIL, "MARK.VALUE", 0, "Bits for marking", 0); 263 } 264 265 // How many mask values do we need to read? We raise an error if this is not found, 266 // unless the MASK.FORCE is set to true in the camera config 267 int nMask = psMetadataLookupS32(&status, header, "MSKNUM"); 268 if (!status) { 269 if (psMetadataLookupBool(&status, config->camera, "MASK.FORCE")) { 270 psWarning("No mask values in header. Assuming MASKS recipe is accurate because of MASK.FORCE"); 271 return true; 272 } 273 psError(PS_ERR_UNKNOWN, true, "Unable to find MSKNUM in header."); 274 return false; 275 } 276 277 // Loop over the expected number of header mask names. For each named mask value, there 278 // should be a pair of header keywords, one for the name and one for the value 279 char namekey[80]; // Keyword name for symbolic name of mask entry 280 char valuekey[80]; // Keyword name for value of mask entry 281 for (int i = 0; i < nMask; i++) { 282 snprintf(namekey, 64, "MSKNAM%02d", i); 283 snprintf(valuekey, 64, "MSKVAL%02d", i); 284 285 char *name = psMetadataLookupStr(&status, header, namekey); 286 if (!status || !name) { 287 psWarning("Unable to find header keyword %s when parsing mask", namekey); 288 continue; 289 } 290 291 psImageMaskType headerValue = psMetadataLookupImageMaskFromGeneric (&status, header, valuekey); 292 if (!status) { 293 psWarning("Failed to get mask value %s from header, skipping", valuekey); 294 continue; 295 } 296 297 // since we may read multiple mask files, we need to warn (or error?) if any of the 298 // header mask values conflict with other header mask values; However, the original 299 // mask values from the recipe do not need to match the header values. 300 301 // when we add a header mask value, we will also add the NAME.ALREADY entry; check for 302 // the NAME.ALREADY entry to see if we have previously added this mask value from a 303 // header. 304 305 psString nameAlready = NULL; // Name of key with ".ALREADY" added 306 psStringAppend(&nameAlready, "%s.ALREADY", name); 307 bool already = psMetadataLookupBool(&status, recipe, nameAlready); // Already read this one? 308 309 bool inRecipe = false; 310 psImageMaskType recipeValue = psMetadataLookupImageMaskFromGeneric (&inRecipe, recipe, name); 311 if (!inRecipe) { 312 psWarning("Mask value %s is not defined in the recipe", name); 313 } 314 315 if (already) { 316 assert (inRecipe); // XXX makes no sense for NAME.ALREADY to be in without NAME 317 if (recipeValue != headerValue) { 318 psWarning("New mask header value does not match previously loaded entry: %x vs %x", headerValue, recipeValue); 319 psMetadataAddImageMask(recipe, PS_LIST_TAIL, name, PS_META_REPLACE, "Bitmask bit value", headerValue); 320 // XXX alternatively, error here 321 } 322 } else { 323 psMetadataAddBool(recipe, PS_LIST_TAIL, nameAlready, 0, "Already read this mask value", true); 324 psMetadataAddImageMask(recipe, PS_LIST_TAIL, name, PS_META_REPLACE, "Bitmask bit value", headerValue); 325 } 326 327 psFree(nameAlready); 328 } 329 330 return true; 331 } 332 333 // write the named mask bits to the header 334 bool pmConfigMaskWriteHeader(const pmConfig *config, psMetadata *header) 335 { 336 PS_ASSERT_PTR_NON_NULL(config, false); 337 PS_ASSERT_METADATA_NON_NULL(header, false); 338 339 pmConfigMaskRemoveHeaderKeywords(header, "MSKNAM"); 340 pmConfigMaskRemoveHeaderKeywords(header, "MSKVAL"); 341 if (psMetadataLookup(header, "MSKNUM")) { 342 psMetadataRemoveKey(header, "MSKNUM"); 343 } 344 345 char namekey[80]; 346 char valuekey[80]; 347 348 psMetadata *recipe = psMetadataLookupMetadata(NULL, config->recipes, "MASKS"); // The recipe 349 if (!recipe) { 350 psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find MASKS recipe."); 351 return false; 352 } 353 354 int nMask = 0; 355 356 psMetadataIterator *iter = psMetadataIteratorAlloc(recipe, PS_LIST_HEAD, NULL); // Iterator 357 psMetadataItem *item; // Item from iteration 358 while ((item = psMetadataGetAndIncrement(iter))) { 359 360 // XXX this would give a false positive for mask which include '.ALREADY' in their names 361 char *ptr = strstr (item->name, ".ALREADY"); 362 if (ptr) continue; 363 364 psU64 fullValue = 0; 365 switch (item->type) { 366 case PS_DATA_U8: 367 fullValue = item->data.U8; 368 break; 369 case PS_DATA_U16: 370 fullValue = item->data.U16; 371 break; 372 case PS_DATA_U32: 373 fullValue = item->data.U32; 374 break; 375 case PS_DATA_U64: 376 fullValue = item->data.U64; 377 break; 378 default: 379 psWarning("mask recipe entry %s is not a bit value\n", item->name); 380 continue; 381 } 382 assert (fullValue <= PS_MAX_IMAGE_MASK_TYPE); // this should have been asserted on read... 383 384 snprintf(namekey, 64, "MSKNAM%02d", nMask); 385 snprintf(valuekey, 64, "MSKVAL%02d", nMask); 386 387 psMetadataAddStr(header, PS_LIST_TAIL, namekey, 0, "Bitmask bit name", item->name); 388 psMetadataAddImageMask(header, PS_LIST_TAIL, valuekey, 0, "Bitmask bit value", fullValue); 389 nMask++; 390 } 391 psFree(iter); 392 393 psMetadataAddS32(header, PS_LIST_TAIL, "MSKNUM", 0, "Bitmask bit count", nMask); 394 return true; 395 } 396 397 398 bool pmConfigMaskSetBits(psImageMaskType *outMaskValue, psImageMaskType *outMarkValue, const pmConfig *config) 399 { 400 PS_ASSERT_PTR_NON_NULL(config, false); 401 402 psMetadata *recipe = psMetadataLookupMetadata(NULL, config->recipes, "MASKS"); // The recipe 403 if (!recipe) { 404 psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find MASKS recipe."); 405 return false; 406 } 407 408 bool status = pmConfigMaskSetInMetadata(outMaskValue, outMarkValue, recipe); 409 return status; 410 } 411 185 412 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// 186 413 // FPA version of mask functions. These are not ready to go yet. … … 188 415 189 416 #if 0 417 418 bool pmFPAMaskWriteHeader(psMetadata *header, const pmFPA *fpa) 419 { 420 PS_ASSERT_METADATA_NON_NULL(header, false); 421 PS_ASSERT_PTR_NON_NULL(fpa, false); 422 423 // clear out the header of the associated keywords: 424 pmConfigMaskRemoveHeaderKeywords(header, "MSKNAM"); 425 pmConfigMaskRemoveHeaderKeywords(header, "MSKVAL"); 426 if (psMetadataLookup(header, "MSKNUM")) { 427 psMetadataRemoveKey(header, "MSKNUM"); 428 } 429 430 char namekey[80], valuekey[80]; // Mask name and mask value header keywords 431 int numMask = 0; // Number of mask entries 432 433 psMetadataIterator *iter = psMetadataIteratorAlloc(fpa->masks, PS_LIST_HEAD, NULL); // Iterator 434 psMetadataItem *item; // Item from iteration 435 while ((item = psMetadataGetAndIncrement(iter))) { 436 if (item->type != PS_TYPE_IMAGE_MASK) { 437 psWarning("mask recipe entry %s is not of a mask type (%x)", item->name, item->type); 438 continue; 439 } 440 441 snprintf(namekey, 64, "MSKNAM%02d", numMask); 442 snprintf(valuekey, 64, "MSKVAL%02d", numMask); 443 444 psMetadataAddStr(header, PS_LIST_TAIL, namekey, 0, "Bitmask bit name", item->name); 445 psMetadataAddImageMask(header, PS_LIST_TAIL, valuekey, 0, "Bitmask bit value", item->data.PS_TYPE_IMAGE_MASK_DATA); 446 numMask++; 447 } 448 psFree(iter); 449 450 return psMetadataAddS32(header, PS_LIST_TAIL, "MSKNUM", 0, "Number of named mask entries", numMask); 451 } 452 190 453 bool pmFPAMaskSetValues(psImageMaskType *outMaskValue, psImageMaskType *outMarkValue, pmFPA *fpa) 191 454 { … … 202 465 203 466 if (fpa->masks) { 204 return maskGet(fpa->masks, masks);467 return pmConfigMaskGetFromMetadata(fpa->masks, masks); 205 468 } 206 469 return pmConfigMaskGet(masks, config); … … 295 558 return true; 296 559 } 297 298 299 bool pmFPAMaskWriteHeader(psMetadata *header, const pmFPA *fpa)300 {301 PS_ASSERT_METADATA_NON_NULL(header, false);302 PS_ASSERT_PTR_NON_NULL(fpa, false);303 304 maskRemoveHeader(header, "MSKNAM");305 maskRemoveHeader(header, "MSKVAL");306 if (psMetadataLookup(header, "MSKNUM")) {307 psMetadataRemoveKey(header, "MSKNUM");308 }309 310 char namekey[80], valuekey[80]; // Mask name and mask value header keywords311 int numMask = 0; // Number of mask entries312 313 psMetadataIterator *iter = psMetadataIteratorAlloc(fpa->masks, PS_LIST_HEAD, NULL); // Iterator314 psMetadataItem *item; // Item from iteration315 while ((item = psMetadataGetAndIncrement(iter))) {316 if (item->type != PS_TYPE_IMAGE_MASK) {317 psWarning("mask recipe entry %s is not of a mask type (%x)", item->name, item->type);318 continue;319 }320 321 snprintf(namekey, 64, "MSKNAM%02d", numMask);322 snprintf(valuekey, 64, "MSKVAL%02d", numMask);323 324 psMetadataAddStr(header, PS_LIST_TAIL, namekey, 0, "Bitmask bit name", item->name);325 psMetadataAddImageMask(header, PS_LIST_TAIL, valuekey, 0, "Bitmask bit value", item->data.PS_TYPE_IMAGE_MASK_DATA);326 numMask++;327 }328 psFree(iter);329 330 return psMetadataAddS32(header, PS_LIST_TAIL, "MSKNUM", 0, "Number of named mask entries", numMask);331 }332 333 560 #endif 334 335 336 psImageMaskType pmConfigMaskGet(const char *masks, const pmConfig *config)337 {338 psAssert(config, "Require configuration");339 PS_ASSERT_STRING_NON_EMPTY(masks, 0);340 341 bool mdok; // Status of MD lookup342 psMetadata *recipe = psMetadataLookupMetadata(&mdok, config->recipes, "MASKS"); // The recipe343 if (!recipe) {344 psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find MASKS recipe.");345 return 0;346 }347 return maskGet(recipe, masks);348 }349 350 351 bool pmConfigMaskSet(const pmConfig *config, const char *maskName, psImageMaskType maskValue)352 {353 psAssert(config, "Require configuration");354 PS_ASSERT_STRING_NON_EMPTY(maskName, false);355 356 psMetadata *recipe = psMetadataLookupMetadata(NULL, config->recipes, "MASKS"); // The recipe357 if (!recipe) {358 psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find MASKS recipe.");359 return false;360 }361 362 return psMetadataAddImageMask(recipe, PS_LIST_TAIL, maskName, PS_META_REPLACE, NULL, maskValue);363 }364 365 366 // replace the named masks in the recipe with values in the header:367 // replace only the names in the header in the recipe368 bool pmConfigMaskReadHeader(pmConfig *config, const psMetadata *header)369 {370 PS_ASSERT_PTR_NON_NULL(config, false);371 PS_ASSERT_METADATA_NON_NULL(header, false);372 373 bool status = false;374 375 psMetadata *recipe = psMetadataLookupMetadata(NULL, config->recipes, "MASKS"); // The recipe376 if (!recipe) {377 psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find MASKS recipe.");378 return false;379 }380 381 // MASK.VALUE and MARK.VALUE aren't usually set in the recipe, but may be set in the header: create fake382 // versions so that it won't complain later383 if (!psMetadataLookup(recipe, "MASK.VALUE")) {384 psMetadataAddImageMask(recipe, PS_LIST_TAIL, "MASK.VALUE", 0, "Bits to mask", 0);385 }386 if (!psMetadataLookup(recipe, "MARK.VALUE")) {387 psMetadataAddImageMask(recipe, PS_LIST_TAIL, "MARK.VALUE", 0, "Bits for marking", 0);388 }389 390 int nMask = psMetadataLookupS32(&status, header, "MSKNUM");391 if (!status) {392 if (psMetadataLookupBool(&status, config->camera, "MASK.FORCE")) {393 psWarning("No mask values in header. Assuming MASKS recipe is accurate because of MASK.FORCE");394 return true;395 }396 psError(PS_ERR_UNKNOWN, true, "Unable to find MSKNUM in header.");397 return false;398 }399 400 char namekey[80]; // Keyword name for symbolic name of mask entry401 char valuekey[80]; // Keyword name for value of mask entry402 for (int i = 0; i < nMask; i++) {403 snprintf(namekey, 64, "MSKNAM%02d", i);404 snprintf(valuekey, 64, "MSKVAL%02d", i);405 406 char *name = psMetadataLookupStr(&status, header, namekey);407 if (!status || !name) {408 psWarning("Unable to find header keyword %s when parsing mask", namekey);409 continue;410 }411 psImageMaskType bit = psMetadataLookupImageMask(&status, header, valuekey);412 if (!status) {413 psWarning("Unable to find header keyword %s when parsing mask", namekey);414 continue;415 }416 417 // XXX validate that bit is a 2^n value?418 419 psString nameAlready = NULL; // Name of key with ".ALREADY" added420 psStringAppend(&nameAlready, "%s.ALREADY", name);421 bool already = psMetadataLookupBool(&status, recipe, nameAlready); // Already read this one?422 423 psMetadataItem *item = psMetadataLookup(recipe, name); // Item in recipe with current value424 if (item && item->type != PS_TYPE_IMAGE_MASK) {425 psWarning("Mask recipe entry is not of a mask type (%x)", item->type);426 item->type = PS_TYPE_IMAGE_MASK;427 }428 429 if (already) {430 if (item && item->data.PS_TYPE_IMAGE_MASK_DATA != bit) {431 psWarning("New mask recipe entry doesn't match previously loaded entry: %x vs %x",432 bit, item->data.PS_TYPE_IMAGE_MASK_DATA);433 }434 } else {435 psMetadataAddBool(recipe, PS_LIST_TAIL, nameAlready, 0, "Already read this mask value", true);436 }437 438 if (!item) {439 psWarning("Mask recipe entry %s not in recipe\n", name);440 psMetadataAddImageMask(recipe, PS_LIST_TAIL, name, 0, "Bitmask bit value", bit);441 } else {442 item->data.PS_TYPE_IMAGE_MASK_DATA = bit;443 }444 445 psFree(nameAlready);446 }447 448 449 return true;450 }451 452 453 454 // write the named mask bits to the header455 bool pmConfigMaskWriteHeader(const pmConfig *config, psMetadata *header)456 {457 PS_ASSERT_PTR_NON_NULL(config, false);458 PS_ASSERT_METADATA_NON_NULL(header, false);459 460 maskRemoveHeader(header, "MSKNAM");461 maskRemoveHeader(header, "MSKVAL");462 if (psMetadataLookup(header, "MSKNUM")) {463 psMetadataRemoveKey(header, "MSKNUM");464 }465 466 char namekey[80];467 char valuekey[80];468 469 psMetadata *recipe = psMetadataLookupMetadata(NULL, config->recipes, "MASKS"); // The recipe470 if (!recipe) {471 psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find MASKS recipe.");472 return false;473 }474 475 int nMask = 0;476 477 psMetadataIterator *iter = psMetadataIteratorAlloc(recipe, PS_LIST_HEAD, NULL); // Iterator478 psMetadataItem *item; // Item from iteration479 while ((item = psMetadataGetAndIncrement(iter))) {480 if (strcmp(item->name + strlen(item->name) - strlen(".ALREADY"), ".ALREADY") == 0) {481 continue;482 }483 484 if (item->type != PS_TYPE_IMAGE_MASK) {485 psWarning("mask recipe entry %s is not a bit value\n", item->name);486 continue;487 }488 489 snprintf(namekey, 64, "MSKNAM%02d", nMask);490 snprintf(valuekey, 64, "MSKVAL%02d", nMask);491 492 psMetadataAddStr(header, PS_LIST_TAIL, namekey, 0, "Bitmask bit name", item->name);493 psMetadataAddImageMask(header, PS_LIST_TAIL, valuekey, 0, "Bitmask bit value", item->data.PS_TYPE_IMAGE_MASK_DATA);494 nMask++;495 }496 psFree(iter);497 498 psMetadataAddS32(header, PS_LIST_TAIL, "MSKNUM", 0, "Bitmask bit count", nMask);499 return true;500 }501 502 503 bool pmConfigMaskSetBits(psImageMaskType *outMaskValue, psImageMaskType *outMarkValue, const pmConfig *config)504 {505 PS_ASSERT_PTR_NON_NULL(config, false);506 507 psMetadata *recipe = psMetadataLookupMetadata(NULL, config->recipes, "MASKS"); // The recipe508 if (!recipe) {509 psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find MASKS recipe.");510 return false;511 }512 513 return maskSetValues(outMaskValue, outMarkValue, recipe);514 } -
branches/eam_branch_20081230/psModules/src/config/pmConfigMask.h
r21079 r21143 4 4 * @author Paul Price, IfA 5 5 * 6 * @version $Revision: 1.4.30. 1$ $Name: not supported by cvs2svn $7 * @date $Date: 2009-01- 02 05:13:00$6 * @version $Revision: 1.4.30.2 $ $Name: not supported by cvs2svn $ 7 * @date $Date: 2009-01-20 02:56:51 $ 8 8 * Copyright 2007 Institute for Astronomy, University of Hawaii 9 9 */ … … 19 19 /// @addtogroup Config Configuration System 20 20 /// @{ 21 22 // structure to hold the properties of a mask value 23 typedef struct { 24 char *badMaskName; // name for "bad" (i.e., mask me please) pixels 25 char *fallbackName; // Fallback name in case a bad mask name is not defined 26 psImageMaskType defaultMaskValue; // Default value in case a bad mask name and its fallback are not defined 27 bool isBad; // include this value as part of the MASK.VALUE entry (generically bad) 28 } pmConfigMaskInfo; 29 30 // pmConfigMaskSetInMetadata examines named mask values and set the bits for maskValue and 31 // markValue. Ensures that the below-named mask values are set, and calculates the mask value 32 // to catch all of the mask values marked as 'bad'. Supplies the fallback name if the primary 33 // name is not found, or the default values if the fallback name is not found. 34 bool pmConfigMaskSetInMetadata(psImageMaskType *outMaskValue, // Value of MASK.VALUE, returned 35 psImageMaskType *outMarkValue, // Value of MARK.VALUE, returned 36 psMetadata *source // Source of mask bits 37 ); 38 39 40 // Get a mask value by name(s) 41 psImageMaskType pmConfigMaskGetFromMetadata(psMetadata *source, // Source of masks 42 const char *masks // Mask values to get 43 ); 44 45 46 // lookup an image mask value by name from a psMetadata, without requiring the entry to 47 // be of type psImageMaskType, but verifying that it will fit in psImageMaskType 48 psImageMaskType psMetadataLookupImageMaskFromGeneric (bool *status, const psMetadata *md, const char *name); 49 50 // Remove from the header keywords starting with the provided string 51 int pmConfigMaskRemoveHeaderKeywords(psMetadata *header, // Header from which to remove keywords 52 const char *start // Remove keywords that start with this string 53 ); 21 54 22 55 /// Return a mask value given a list of symbolic names
Note:
See TracChangeset
for help on using the changeset viewer.
