Changeset 15630 for trunk/psLib/src/fits/psFitsFloat.c
- Timestamp:
- Nov 15, 2007, 3:04:56 PM (18 years ago)
- File:
-
- 1 edited
-
trunk/psLib/src/fits/psFitsFloat.c (modified) (6 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psLib/src/fits/psFitsFloat.c
r15335 r15630 4 4 5 5 #include <ieee754.h> 6 #include <string.h> 7 #include <assert.h> 6 8 7 9 #include "psAbort.h" … … 9 11 #include "psError.h" 10 12 #include "psImage.h" 11 #include "psMetadata.h"12 #include "psRandom.h"13 13 #include "psFits.h" 14 #include "psTrace.h" 15 #include "psMemory.h" 14 16 15 17 #include "psFitsFloat.h" 16 18 17 #define BIAS_FLOAT_16_0 10 // Exponent bias 19 #define BIAS_FLOAT_16_0 10 // Exponent bias for FLOAT_16_0 20 21 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// 22 // Private functions 23 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// 18 24 19 25 union float_16_0 { … … 27 33 } f16; 28 34 }; 29 30 35 31 36 … … 57 62 } 58 63 64 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// 65 // Public functions 66 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// 59 67 60 psImage *psFitsScaleGenerate(psFits *fits, const psImage *image, int bitpix, psRandom *rng)61 {62 PS_ASSERT_FITS_NON_NULL(fits, NULL);63 PS_ASSERT_FITS_WRITABLE(fits, NULL);64 PS_ASSERT_IMAGE_NON_NULL(image, NULL);65 PS_ASSERT_IMAGE_TYPE_F32_OR_F64(image, NULL);66 PS_ASSERT_RANDOM_NON_NULL(rng, NULL);67 68 68 psElemType outType; // Type for output image 69 // Choosing to use signed types because those don't require BSCALE,BZERO to represent them in the FITS 70 // file. 71 switch (bitpix) { 72 case 8: 73 outType = PS_TYPE_S8; 74 break; 75 case 16: 76 outType = PS_TYPE_S16; 77 break; 78 case 32: 79 outType = PS_TYPE_S32; 80 break; 81 case 64: 82 outType = PS_TYPE_S64; 83 break; 84 default: 85 psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Target bitpix (%d) is not one of 8,16,32,64", bitpix); 86 return NULL; 87 } 88 89 int numCols = image->numCols, numRows = image->numRows; 90 double range = pow(2.0, bitpix); // Range of values for target BITPIX 91 psImage *out = psImageAlloc(numCols, numRows, outType); // Output scaled image 92 93 #define SCALE_GENERATE_CASE(IN, INTYPE, OUT, OUTTYPE) \ 94 case PS_TYPE_##OUTTYPE: { \ 95 for (int y = 0; y < numRows; y++) { \ 96 for (int x = 0; x < numCols; x++) { \ 97 ps##INTYPE random = psRandomUniform(rng) - 0.5; /* Randomise the quantisation */ \ 98 (OUT)->data.OUTTYPE[y][x] = ((IN)->data.INTYPE[y][x] - zero) * scale + random; \ 99 } \ 100 } \ 101 break; \ 102 } 103 104 #define SCALE_DETERMINE_CASE(IN, INTYPE, OUT) \ 105 case PS_TYPE_##INTYPE: { \ 106 ps##INTYPE min = INFINITY, max = -INFINITY; /* Minimum and maximum values */ \ 107 for (int y = 0; y < numRows; y++) { \ 108 for (int x = 0; x < numCols; x++) { \ 109 ps##INTYPE value = (IN)->data.INTYPE[y][x]; /* Value of interest */ \ 110 if (isfinite(value)) { \ 111 if (value < min) { \ 112 min = value; \ 113 } \ 114 if (value > max) { \ 115 max = value; \ 116 } \ 117 } \ 118 } \ 119 } \ 120 ps##INTYPE scale = range / (max - min); \ 121 ps##INTYPE zero = min - 0.5 * range; /* Minimum value for twos-complement int is - 2^(bitpix-1) */ \ 122 fits->bscale = 1.0 / scale; \ 123 fits->bzero = zero; \ 124 switch (outType) { \ 125 SCALE_GENERATE_CASE(IN, INTYPE, OUT, S8); \ 126 SCALE_GENERATE_CASE(IN, INTYPE, OUT, S16); \ 127 SCALE_GENERATE_CASE(IN, INTYPE, OUT, S32); \ 128 SCALE_GENERATE_CASE(IN, INTYPE, OUT, S64); \ 129 default: \ 130 psAbort("Should be unreachable."); \ 131 } \ 132 break; \ 133 } 134 135 switch (image->type.type) { 136 SCALE_DETERMINE_CASE(image, F32, out); 137 SCALE_DETERMINE_CASE(image, F64, out); 138 default: 139 psAbort("Should be unreachable."); 140 } 141 142 return out; 143 } 144 145 psImage *psFitsScaleApply(const psImage *image, double bscale, double bzero, psElemType type) 69 psImage *psFitsFloatImageWrite(const psImage *image, psFitsFloat type) 146 70 { 147 71 PS_ASSERT_IMAGE_NON_NULL(image, NULL); 148 149 if (bscale == 0.0) { 150 return psMemIncrRefCounter(image); 151 } 152 153 switch ( 154 155 156 psImage *psFitsFloatImageWrite(const psImage *image, 157 psMetadata *header, 158 psFitsFloat type 159 ) 160 { 161 PS_ASSERT_IMAGE_NON_NULL(image, NULL); 162 PS_ASSERT_METADATA_NON_NULL(header, NULL); // Need the header, so we can mark it as compressed 72 PS_ASSERT_IMAGE_TYPE(image, PS_TYPE_F32, NULL); 163 73 164 74 psImage *output = NULL; // Output image, to return 165 psString convName = NULL; // Convention name166 75 167 76 switch (type) { 77 case PS_FITS_FLOAT_NONE: 78 // No conversion to be performed 79 return psMemIncrRefCounter((psImage*)image); // Casting away "const" 168 80 case PS_FITS_FLOAT_16_0: 169 81 output = psImageAlloc(image->numCols, image->numRows, PS_TYPE_S16); // Output image … … 173 85 } 174 86 } 175 convName = psStringCopy("FLOAT_16_0");176 87 break; 177 88 default: … … 180 91 } 181 92 182 psMetadataAddStr(header, PS_LIST_TAIL, "PSBITPIX", PS_META_REPLACE, "Pan-STARRS bit encoding", convName);183 184 93 return output; 185 94 } 186 95 187 psImage *psFitsFloatImageRead(const psFits *fits, 188 const psImage *image 189 ) 96 97 psImage *psFitsFloatImageRead(psImage *out, const psImage *in, psFitsFloat type) 190 98 { 191 PS_ASSERT_FITS_NON_NULL(fits, NULL); 192 PS_ASSERT_IMAGE_NON_NULL(image, NULL); 99 PS_ASSERT_IMAGE_NON_NULL(in, NULL); 193 100 194 bool mdok; // Status of MD lookup 195 const char *convName = psMetadataLookupStr(&mdok, header, "PSBITPIX"); // Convention used 196 if (!mdok || !convName) { 197 // It's not a custom floating-point image 198 return psMemIncrRefCounter(image); 101 psElemType elem = psFitsFloatImageType(type); // Type for elements 102 if (elem == 0) { 103 psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Unable to recognise convention: %x", type); 104 return NULL; 199 105 } 200 106 201 psImage *output = NULL; // Output image, to return107 int numCols = in->numCols, numRows = in->numRows; // Size of image 202 108 203 if (strcmp(convName, "FLOAT_16_0") == 0 && image->type.type == PS_TYPE_S16) { 204 output = psImageAlloc(image->numCols, image->numRows, PS_TYPE_F32); // Output image 205 for (int y = 0; y < image->numRows; y++) { 206 for (int x = 0; x < image->numCols; x++) { 207 output->data.F32[y][x] = convertF32fromFloat16_0(image->data.S16[y][x]); 109 out = psImageRecycle(out, numCols, numRows, elem); 110 111 switch (type) { 112 case PS_FITS_FLOAT_16_0: 113 if (in->type.type != PS_TYPE_S16) { 114 psError(PS_ERR_BAD_PARAMETER_VALUE, true, 115 "Convention claims to be FLOAT_16_0, but image type is not S16."); 116 return NULL; 117 } 118 assert(out->type.type == PS_TYPE_F32); 119 for (int y = 0; y < numRows; y++) { 120 for (int x = 0; x < numCols; x++) { 121 out->data.F32[y][x] = convertF32fromFloat16_0(in->data.S16[y][x]); 208 122 } 209 123 } 210 return output; 124 return out; 125 case PS_FITS_FLOAT_NONE: 126 default: 127 psAbort("Should be unreachable"); 128 } 129 return NULL; 130 } 131 132 psElemType psFitsFloatImageType(psFitsFloat type) 133 { 134 switch (type) { 135 case PS_FITS_FLOAT_16_0: 136 return PS_TYPE_F32; 137 case PS_FITS_FLOAT_NONE: 138 default: 139 return 0; // Doesn't correspond to ANY type --- should flag a real error 140 } 141 } 142 143 144 psFitsFloat psFitsFloatTypeFromString(const char *string) 145 { 146 PS_ASSERT_STRING_NON_EMPTY(string, PS_FITS_FLOAT_NONE); 147 148 if (strcmp(string, "FLOAT_16_0") == 0) { 149 return PS_FITS_FLOAT_16_0; 211 150 } 212 151 213 psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Unable to recognise PSBITPIX convention name: %s", convName); 214 return NULL; 215 216 return output; 152 psError(PS_ERR_BAD_PARAMETER_VALUE, true, 153 "Unable to recognise custom floating-point convention name: %s", string); 154 return PS_FITS_FLOAT_NONE; 217 155 }
Note:
See TracChangeset
for help on using the changeset viewer.
