Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: ASI CEOS Translator
4 : * Purpose: CEOS field layout recipes.
5 : * Author: Paul Lahaie, pjlahaie@atlsci.com
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2000, Atlantis Scientific Inc
9 : *
10 : * SPDX-License-Identifier: MIT
11 : ****************************************************************************/
12 :
13 : #include "ceos.h"
14 :
15 : /* Array of Datatypes and their names/values */
16 :
17 : typedef struct
18 : {
19 : const char *String;
20 : int Type;
21 : } CeosStringType_t;
22 :
23 : typedef struct
24 : {
25 : int (*function)(CeosSARVolume_t *volume, const void *token);
26 : const void *token;
27 : const char *name;
28 : } RecipeFunctionData_t;
29 :
30 : static const CeosStringType_t CeosDataType[] = {
31 : {"IU1", CEOS_TYP_UCHAR},
32 : {"IU2", CEOS_TYP_USHORT},
33 : {"UI1", CEOS_TYP_UCHAR},
34 : {"UI2", CEOS_TYP_USHORT},
35 : {"CI*2", CEOS_TYP_COMPLEX_CHAR},
36 : {"CI*4", CEOS_TYP_COMPLEX_SHORT},
37 : {"CIS4", CEOS_TYP_COMPLEX_SHORT},
38 : {"CI*8", CEOS_TYP_COMPLEX_LONG},
39 : {"C*8", CEOS_TYP_COMPLEX_FLOAT},
40 : {"R*4", CEOS_TYP_FLOAT},
41 : {NULL, 0}};
42 :
43 : static const CeosStringType_t CeosInterleaveType[] = {{"BSQ", CEOS_IL_BAND},
44 : {" BSQ", CEOS_IL_BAND},
45 : {"BIL", CEOS_IL_LINE},
46 : {" BIL", CEOS_IL_LINE},
47 : {NULL, 0}};
48 :
49 : #define IMAGE_OPT {63, 192, 18, 18}
50 : #define IMAGE_JERS_OPT \
51 : {50, 192, 18, 18} /* Some JERS data uses this instead of IMAGE_OPT */
52 : #define PROC_DATA_REC {50, 11, 18, 20}
53 : #define PROC_DATA_REC_ALT {50, 11, 31, 20}
54 : #define PROC_DATA_REC_ALT2 {50, 11, 31, 50} /* Some cases of ERS 1, 2 */
55 : #define DATA_SET_SUMMARY {18, 10, 18, 20}
56 :
57 : /* NOTE: This seems to be the generic recipe used for most things */
58 : static const CeosRecipeType_t RadarSatRecipe[] = {
59 : {CEOS_REC_NUMCHANS, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 233, 4,
60 : CEOS_REC_TYP_I}, /* Number of channels */
61 : {CEOS_REC_INTERLEAVE, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 269, 4,
62 : CEOS_REC_TYP_A}, /* Interleaving type */
63 : {CEOS_REC_DATATYPE, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 429, 4,
64 : CEOS_REC_TYP_A}, /* Data type */
65 : {CEOS_REC_BPR, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 0, 0,
66 : CEOS_REC_TYP_A}, /* For Default CEOS, this is done using other vals */
67 : {CEOS_REC_LINES, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 237, 8,
68 : CEOS_REC_TYP_I}, /* How many lines */
69 : {CEOS_REC_TBP, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 261, 4, CEOS_REC_TYP_I},
70 : {CEOS_REC_BBP, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 265, 4,
71 : CEOS_REC_TYP_I}, /* Bottom border pixels */
72 : {CEOS_REC_PPL, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 249, 8,
73 : CEOS_REC_TYP_I}, /* Pixels per line */
74 : {CEOS_REC_LBP, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 245, 4,
75 : CEOS_REC_TYP_I}, /* Left Border Pixels */
76 : {CEOS_REC_RBP, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 257, 4,
77 : CEOS_REC_TYP_I}, /* Right Border Pixels */
78 : {CEOS_REC_BPP, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 225, 4,
79 : CEOS_REC_TYP_I}, /* Bytes Per Pixel */
80 : {CEOS_REC_RPL, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 273, 2,
81 : CEOS_REC_TYP_I}, /* Records per line */
82 : {CEOS_REC_PPR, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 0, 0,
83 : CEOS_REC_TYP_I}, /* Pixels Per Record -- need to fill record type */
84 : {CEOS_REC_PDBPR, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 281, 8,
85 : CEOS_REC_TYP_I}, /* pixel data bytes per record */
86 : {CEOS_REC_IDS, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 277, 4,
87 : CEOS_REC_TYP_I}, /* Prefix data per record */
88 : {CEOS_REC_FDL, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 9, 4,
89 : CEOS_REC_TYP_B}, /* Length of Imagry Options Header */
90 : {CEOS_REC_PIXORD, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 0, 0,
91 : CEOS_REC_TYP_I}, /* Must be calculated */
92 : {CEOS_REC_LINORD, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 0, 0,
93 : CEOS_REC_TYP_I}, /* Must be calculated */
94 : {CEOS_REC_PRODTYPE, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 0, 0,
95 : CEOS_REC_TYP_I},
96 :
97 : {CEOS_REC_RECORDSIZE, 1, CEOS_IMAGRY_OPT_FILE, PROC_DATA_REC, 9, 4,
98 : CEOS_REC_TYP_B}, /* The processed image record size */
99 :
100 : /* Some ERS-1 products use an alternate data record subtype2. */
101 : {CEOS_REC_RECORDSIZE, 1, CEOS_IMAGRY_OPT_FILE, PROC_DATA_REC_ALT, 9, 4,
102 : CEOS_REC_TYP_B}, /* The processed image record size */
103 :
104 : /* Yet another ERS-1 and ERS-2 alternate data record subtype2. */
105 : {CEOS_REC_RECORDSIZE, 1, CEOS_IMAGRY_OPT_FILE, PROC_DATA_REC_ALT2, 9, 4,
106 : CEOS_REC_TYP_B}, /* The processed image record size */
107 :
108 : {CEOS_REC_SUFFIX_SIZE, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 289, 4,
109 : CEOS_REC_TYP_I}, /* Suffix data per record */
110 : {0, 0, 0, {0, 0, 0, 0}, 0, 0, 0} /* Last record is Zero */
111 : };
112 :
113 : static const CeosRecipeType_t JersRecipe[] = {
114 : {CEOS_REC_NUMCHANS, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT, 233, 4,
115 : CEOS_REC_TYP_I}, /* Number of channels */
116 : {CEOS_REC_INTERLEAVE, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT, 269, 4,
117 : CEOS_REC_TYP_A}, /* Interleaving type */
118 : {CEOS_REC_DATATYPE, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT, 429, 4,
119 : CEOS_REC_TYP_A}, /* Data type */
120 : {CEOS_REC_BPR, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT, 0, 0,
121 : CEOS_REC_TYP_A}, /* For Default CEOS, this is done using other vals */
122 : {CEOS_REC_LINES, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT, 237, 8,
123 : CEOS_REC_TYP_I}, /* How many lines */
124 : {CEOS_REC_TBP, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT, 261, 4,
125 : CEOS_REC_TYP_I},
126 : {CEOS_REC_BBP, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT, 265, 4,
127 : CEOS_REC_TYP_I}, /* Bottom border pixels */
128 : {CEOS_REC_PPL, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT, 249, 8,
129 : CEOS_REC_TYP_I}, /* Pixels per line */
130 : {CEOS_REC_LBP, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT, 245, 4,
131 : CEOS_REC_TYP_I}, /* Left Border Pixels */
132 : {CEOS_REC_RBP, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT, 257, 4,
133 : CEOS_REC_TYP_I}, /* Isn't available for RadarSAT */
134 : {CEOS_REC_BPP, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT, 225, 4,
135 : CEOS_REC_TYP_I}, /* Bytes Per Pixel */
136 : {CEOS_REC_RPL, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT, 273, 2,
137 : CEOS_REC_TYP_I}, /* Records per line */
138 : {CEOS_REC_PPR, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT, 0, 0,
139 : CEOS_REC_TYP_I}, /* Pixels Per Record -- need to fill record type */
140 : {CEOS_REC_PDBPR, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT, 281, 8,
141 : CEOS_REC_TYP_I}, /* pixel data bytes per record */
142 : {CEOS_REC_IDS, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT, 277, 4,
143 : CEOS_REC_TYP_I}, /* Prefix data per record */
144 : {CEOS_REC_FDL, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT, 9, 4,
145 : CEOS_REC_TYP_B}, /* Length of Imagry Options Header */
146 : {CEOS_REC_PIXORD, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT, 0, 0,
147 : CEOS_REC_TYP_I}, /* Must be calculated */
148 : {CEOS_REC_LINORD, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT, 0, 0,
149 : CEOS_REC_TYP_I}, /* Must be calculated */
150 : {CEOS_REC_PRODTYPE, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT, 0, 0,
151 : CEOS_REC_TYP_I},
152 :
153 : {CEOS_REC_RECORDSIZE, 1, CEOS_IMAGRY_OPT_FILE, PROC_DATA_REC, 9, 4,
154 : CEOS_REC_TYP_B}, /* The processed image record size */
155 :
156 : {CEOS_REC_SUFFIX_SIZE, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT, 289, 4,
157 : CEOS_REC_TYP_I}, /* Suffix data per record */
158 : {0, 0, 0, {0, 0, 0, 0}, 0, 0, 0} /* Last record is Zero */
159 : };
160 :
161 : static const CeosRecipeType_t ScanSARRecipe[] = {
162 : {CEOS_REC_NUMCHANS, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 233, 4,
163 : CEOS_REC_TYP_I}, /* Number of channels */
164 : {CEOS_REC_INTERLEAVE, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 269, 4,
165 : CEOS_REC_TYP_A}, /* Interleaving type */
166 : {CEOS_REC_DATATYPE, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 429, 4,
167 : CEOS_REC_TYP_A}, /* Data type */
168 : {CEOS_REC_LINES, 1, CEOS_ANY_FILE, DATA_SET_SUMMARY, 325, 8,
169 : CEOS_REC_TYP_I}, /* How many lines */
170 : {CEOS_REC_PPL, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 249, 8,
171 : CEOS_REC_TYP_I}, /* Pixels per line */
172 : {CEOS_REC_BPP, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 225, 4,
173 : CEOS_REC_TYP_I}, /* Bytes Per Pixel */
174 : {CEOS_REC_RPL, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 273, 2,
175 : CEOS_REC_TYP_I}, /* Records per line */
176 : {CEOS_REC_IDS, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 277, 4,
177 : CEOS_REC_TYP_I}, /* Prefix data per record */
178 : {CEOS_REC_FDL, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 9, 4,
179 : CEOS_REC_TYP_B}, /* Length of Imagry Options Header */
180 : {CEOS_REC_RECORDSIZE, 1, CEOS_IMAGRY_OPT_FILE, PROC_DATA_REC, 9, 4,
181 : CEOS_REC_TYP_B}, /* The processed image record size */
182 : {CEOS_REC_SUFFIX_SIZE, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 289, 4,
183 : CEOS_REC_TYP_I}, /* Suffix data per record */
184 : {0, 0, 0, {0, 0, 0, 0}, 0, 0, 0} /* Last record is Zero */
185 : };
186 :
187 : static const CeosRecipeType_t SIRCRecipe[] = {
188 : {CEOS_REC_NUMCHANS, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 233, 4,
189 : CEOS_REC_TYP_I}, /* Number of channels */
190 : {CEOS_REC_INTERLEAVE, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 269, 4,
191 : CEOS_REC_TYP_A}, /* Interleaving type */
192 : {CEOS_REC_DATATYPE, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 429, 4,
193 : CEOS_REC_TYP_A}, /* Data type */
194 : {CEOS_REC_LINES, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 237, 8,
195 : CEOS_REC_TYP_I}, /* How many lines */
196 : {CEOS_REC_TBP, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 261, 4, CEOS_REC_TYP_I},
197 : {CEOS_REC_BBP, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 265, 4,
198 : CEOS_REC_TYP_I}, /* Bottom border pixels */
199 : {CEOS_REC_PPL, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 249, 8,
200 : CEOS_REC_TYP_I}, /* Pixels per line */
201 : {CEOS_REC_LBP, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 245, 4,
202 : CEOS_REC_TYP_I}, /* Left Border Pixels */
203 : {CEOS_REC_RBP, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 257, 4,
204 : CEOS_REC_TYP_I}, /* Right Border Pixels */
205 : {CEOS_REC_BPP, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 225, 4,
206 : CEOS_REC_TYP_I}, /* Bytes Per Pixel */
207 : {CEOS_REC_RPL, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 273, 2,
208 : CEOS_REC_TYP_I}, /* Records per line */
209 : {CEOS_REC_IDS, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 277, 4,
210 : CEOS_REC_TYP_I}, /* Prefix data per record */
211 : {CEOS_REC_FDL, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 9, 4,
212 : CEOS_REC_TYP_B}, /* Length of Imagry Options Header */
213 : {CEOS_REC_RECORDSIZE, 1, CEOS_IMAGRY_OPT_FILE, PROC_DATA_REC, 9, 4,
214 : CEOS_REC_TYP_B}, /* The processed image record size */
215 : {CEOS_REC_SUFFIX_SIZE, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 289, 4,
216 : CEOS_REC_TYP_I}, /* Suffix data per record */
217 :
218 : {0, 0, 0, {0, 0, 0, 0}, 0, 0, 0} /* Last record is Zero */
219 : };
220 :
221 : #undef PROC_DATA_REC
222 :
223 : static void ExtractInt(CeosRecord_t *record, int type, unsigned int offset,
224 : unsigned int length, int *value);
225 :
226 : static char *ExtractString(CeosRecord_t *record, unsigned int offset,
227 : unsigned int length, char *string);
228 :
229 : static int GetCeosStringType(const CeosStringType_t *CeosType,
230 : const char *string);
231 :
232 : static int SIRCRecipeFCN(CeosSARVolume_t *volume, const void *token);
233 : static int PALSARRecipeFCN(CeosSARVolume_t *volume, const void *token);
234 :
235 : Link_t *RecipeFunctions = NULL;
236 :
237 2 : void RegisterRecipes(void)
238 : {
239 :
240 2 : AddRecipe(SIRCRecipeFCN, SIRCRecipe, "SIR-C");
241 2 : AddRecipe(ScanSARRecipeFCN, ScanSARRecipe, "ScanSAR");
242 2 : AddRecipe(CeosDefaultRecipe, RadarSatRecipe, "RadarSat");
243 2 : AddRecipe(CeosDefaultRecipe, JersRecipe, "Jers");
244 2 : AddRecipe(PALSARRecipeFCN, RadarSatRecipe, "PALSAR-ALOS");
245 : /* AddRecipe( CeosDefaultRecipe, AtlantisRecipe ); */
246 2 : }
247 :
248 4 : void FreeRecipes(void)
249 :
250 : {
251 : Link_t *l_link;
252 :
253 14 : for (l_link = RecipeFunctions; l_link != NULL; l_link = l_link->next)
254 10 : HFree(l_link->object);
255 :
256 4 : DestroyList(RecipeFunctions);
257 4 : RecipeFunctions = NULL;
258 4 : }
259 :
260 10 : void AddRecipe(int (*function)(CeosSARVolume_t *volume, const void *token),
261 : const void *token, const char *name)
262 : {
263 :
264 : RecipeFunctionData_t *TempData;
265 :
266 : Link_t *Link;
267 :
268 10 : TempData = HMalloc(sizeof(RecipeFunctionData_t));
269 :
270 10 : TempData->function = function;
271 10 : TempData->token = token;
272 10 : TempData->name = name;
273 :
274 10 : Link = ceos2CreateLink(TempData);
275 :
276 10 : if (RecipeFunctions == NULL)
277 : {
278 2 : RecipeFunctions = Link;
279 : }
280 : else
281 : {
282 8 : RecipeFunctions = InsertLink(RecipeFunctions, Link);
283 : }
284 10 : }
285 :
286 8 : int CeosDefaultRecipe(CeosSARVolume_t *volume, const void *token)
287 : {
288 : const CeosRecipeType_t *recipe;
289 : CeosRecord_t *record;
290 8 : CeosTypeCode_t TypeCode = {0};
291 8 : struct CeosSARImageDesc *ImageDesc = &(volume->ImageDesc);
292 : char temp_str[1024];
293 : int i /*, temp_int */;
294 :
295 : #define DoExtractInt(a) \
296 : ExtractInt(record, recipe[i].Type, recipe[i].Offset, recipe[i].Length, &a)
297 :
298 8 : if (token == NULL)
299 : {
300 0 : return 0;
301 : }
302 :
303 8 : memset(ImageDesc, 0, sizeof(struct CeosSARImageDesc));
304 :
305 : /* temp_imagerecipe = (CeosSARImageDescRecipe_t *) token;
306 : recipe = temp_imagerecipe->Recipe; */
307 :
308 8 : recipe = token;
309 :
310 184 : for (i = 0; recipe[i].ImageDescValue != 0; i++)
311 : {
312 176 : if (recipe[i].Override)
313 : {
314 112 : TypeCode.UCharCode.Subtype1 = recipe[i].TypeCode.Subtype1;
315 112 : TypeCode.UCharCode.Type = recipe[i].TypeCode.Type;
316 112 : TypeCode.UCharCode.Subtype2 = recipe[i].TypeCode.Subtype2;
317 112 : TypeCode.UCharCode.Subtype3 = recipe[i].TypeCode.Subtype3;
318 :
319 112 : record = FindCeosRecord(volume->RecordList, TypeCode,
320 112 : recipe[i].FileId, -1, -1);
321 :
322 112 : if (record == NULL)
323 : {
324 : /* temp_int = 0; */
325 : }
326 : else
327 : {
328 :
329 60 : switch (recipe[i].ImageDescValue)
330 : {
331 4 : case CEOS_REC_NUMCHANS:
332 4 : DoExtractInt(ImageDesc->NumChannels);
333 4 : break;
334 4 : case CEOS_REC_LINES:
335 4 : DoExtractInt(ImageDesc->Lines);
336 4 : break;
337 4 : case CEOS_REC_BPP:
338 4 : DoExtractInt(ImageDesc->BytesPerPixel);
339 4 : break;
340 4 : case CEOS_REC_RPL:
341 4 : DoExtractInt(ImageDesc->RecordsPerLine);
342 4 : break;
343 4 : case CEOS_REC_PDBPR:
344 4 : DoExtractInt(ImageDesc->PixelDataBytesPerRecord);
345 4 : break;
346 4 : case CEOS_REC_FDL:
347 4 : DoExtractInt(ImageDesc->FileDescriptorLength);
348 4 : break;
349 4 : case CEOS_REC_IDS:
350 4 : DoExtractInt(ImageDesc->ImageDataStart);
351 : /*
352 : ** This is really reading the quantity of prefix data
353 : ** per data record. We want the offset from the very
354 : ** beginning of the record to the data, so we add
355 : *another
356 : ** 12 to that. I think some products incorrectly
357 : *indicate
358 : ** 192 (prefix+12) instead of 180 so if we see 192
359 : *assume
360 : ** the 12 bytes of record start data has already been
361 : ** added. Frank Warmerdam.
362 : */
363 4 : if (ImageDesc->ImageDataStart != 192)
364 2 : ImageDesc->ImageDataStart += 12;
365 4 : break;
366 4 : case CEOS_REC_SUFFIX_SIZE:
367 4 : DoExtractInt(ImageDesc->ImageSuffixData);
368 4 : break;
369 8 : case CEOS_REC_RECORDSIZE:
370 8 : DoExtractInt(ImageDesc->BytesPerRecord);
371 8 : break;
372 4 : case CEOS_REC_PPL:
373 4 : DoExtractInt(ImageDesc->PixelsPerLine);
374 4 : break;
375 0 : case CEOS_REC_TBP:
376 0 : DoExtractInt(ImageDesc->TopBorderPixels);
377 0 : break;
378 0 : case CEOS_REC_BBP:
379 0 : DoExtractInt(ImageDesc->BottomBorderPixels);
380 0 : break;
381 4 : case CEOS_REC_LBP:
382 4 : DoExtractInt(ImageDesc->LeftBorderPixels);
383 4 : break;
384 4 : case CEOS_REC_RBP:
385 4 : DoExtractInt(ImageDesc->RightBorderPixels);
386 4 : break;
387 4 : case CEOS_REC_INTERLEAVE:
388 4 : ExtractString(record, recipe[i].Offset,
389 4 : recipe[i].Length, temp_str);
390 :
391 4 : ImageDesc->ChannelInterleaving =
392 4 : GetCeosStringType(CeosInterleaveType, temp_str);
393 4 : break;
394 4 : case CEOS_REC_DATATYPE:
395 4 : ExtractString(record, recipe[i].Offset,
396 4 : recipe[i].Length, temp_str);
397 :
398 4 : ImageDesc->DataType =
399 4 : GetCeosStringType(CeosDataType, temp_str);
400 4 : break;
401 : }
402 176 : }
403 : }
404 : }
405 :
406 : /* Some files (Telaviv) don't record the number of pixel groups per line.
407 : * Try to derive it from the size of a data group, and the number of
408 : * bytes of pixel data if necessary.
409 : */
410 :
411 8 : if (ImageDesc->PixelsPerLine == 0 &&
412 4 : ImageDesc->PixelDataBytesPerRecord != 0 &&
413 0 : ImageDesc->BytesPerPixel != 0)
414 : {
415 0 : ImageDesc->PixelsPerLine =
416 0 : ImageDesc->PixelDataBytesPerRecord / ImageDesc->BytesPerPixel;
417 0 : CPLDebug("SAR_CEOS", "Guessing PixelPerLine to be %d\n",
418 : ImageDesc->PixelsPerLine);
419 : }
420 :
421 : /* Some files don't have the BytesPerRecord stuff, so we calculate it if
422 : * possible */
423 :
424 8 : if (ImageDesc->BytesPerRecord == 0 && ImageDesc->RecordsPerLine == 1 &&
425 0 : ImageDesc->PixelsPerLine > 0 && ImageDesc->BytesPerPixel > 0)
426 : {
427 : CeosRecord_t *img_rec;
428 :
429 0 : ImageDesc->BytesPerRecord =
430 0 : ImageDesc->PixelsPerLine * ImageDesc->BytesPerPixel +
431 0 : ImageDesc->ImageDataStart + ImageDesc->ImageSuffixData;
432 :
433 0 : TypeCode.UCharCode.Subtype1 = 0xed;
434 0 : TypeCode.UCharCode.Type = 0xed;
435 0 : TypeCode.UCharCode.Subtype2 = 0x12;
436 0 : TypeCode.UCharCode.Subtype3 = 0x12;
437 :
438 0 : img_rec = FindCeosRecord(volume->RecordList, TypeCode,
439 : CEOS_IMAGRY_OPT_FILE, -1, -1);
440 0 : if (img_rec == NULL)
441 : {
442 0 : CPLDebug("SAR_CEOS",
443 : "Unable to find imagery rec to check record length.");
444 0 : return 0;
445 : }
446 :
447 0 : if (img_rec->Length != ImageDesc->BytesPerRecord)
448 : {
449 0 : CPLDebug("SAR_CEOS",
450 : "Guessed record length (%d) did not match\n"
451 : "actual imagery record length (%d), recipe fails.",
452 : ImageDesc->BytesPerRecord, img_rec->Length);
453 0 : return 0;
454 : }
455 : }
456 :
457 8 : if (ImageDesc->PixelsPerRecord == 0 && ImageDesc->BytesPerRecord != 0 &&
458 8 : ImageDesc->BytesPerPixel != 0)
459 : {
460 4 : ImageDesc->PixelsPerRecord =
461 4 : ((ImageDesc->BytesPerRecord -
462 4 : (ImageDesc->ImageSuffixData + ImageDesc->ImageDataStart)) /
463 4 : ImageDesc->BytesPerPixel);
464 :
465 4 : if (ImageDesc->PixelsPerRecord > ImageDesc->PixelsPerLine)
466 0 : ImageDesc->PixelsPerRecord = ImageDesc->PixelsPerLine;
467 : }
468 :
469 : /* If we didn't get a data type, try guessing. */
470 8 : if (ImageDesc->DataType == 0 && ImageDesc->BytesPerPixel != 0 &&
471 0 : ImageDesc->NumChannels != 0)
472 : {
473 0 : int nDataTypeSize = ImageDesc->BytesPerPixel / ImageDesc->NumChannels;
474 :
475 0 : if (nDataTypeSize == 1)
476 0 : ImageDesc->DataType = CEOS_TYP_UCHAR;
477 0 : else if (nDataTypeSize == 2)
478 0 : ImageDesc->DataType = CEOS_TYP_USHORT;
479 : }
480 :
481 : /* Sanity checking */
482 :
483 8 : if (ImageDesc->PixelsPerLine == 0 || ImageDesc->Lines == 0 ||
484 4 : ImageDesc->RecordsPerLine == 0 || ImageDesc->ImageDataStart == 0 ||
485 4 : ImageDesc->FileDescriptorLength == 0 || ImageDesc->DataType == 0 ||
486 4 : ImageDesc->NumChannels == 0 || ImageDesc->BytesPerPixel == 0 ||
487 4 : ImageDesc->ChannelInterleaving == 0 || ImageDesc->BytesPerRecord == 0)
488 : {
489 4 : return 0;
490 : }
491 : else
492 : {
493 :
494 4 : ImageDesc->ImageDescValid = TRUE;
495 4 : return 1;
496 : }
497 : }
498 :
499 0 : int ScanSARRecipeFCN(CeosSARVolume_t *volume, const void *token)
500 : {
501 0 : struct CeosSARImageDesc *ImageDesc = &(volume->ImageDesc);
502 :
503 0 : memset(ImageDesc, 0, sizeof(struct CeosSARImageDesc));
504 :
505 0 : if (CeosDefaultRecipe(volume, token))
506 : {
507 0 : ImageDesc->Lines *= 2;
508 0 : return 1;
509 : }
510 :
511 0 : return 0;
512 : }
513 :
514 0 : static int SIRCRecipeFCN(CeosSARVolume_t *volume, const void *token)
515 : {
516 0 : struct CeosSARImageDesc *ImageDesc = &(volume->ImageDesc);
517 0 : CeosTypeCode_t TypeCode = {0};
518 : CeosRecord_t *record;
519 : char szSARDataFormat[29];
520 :
521 0 : memset(ImageDesc, 0, sizeof(struct CeosSARImageDesc));
522 :
523 : /* -------------------------------------------------------------------- */
524 : /* First, we need to check if the "SAR Data Format Type */
525 : /* identifier" is set to "COMPRESSED CROSS-PRODUCTS" which is */
526 : /* pretty idiosyncratic to SIRC products. It might also appear */
527 : /* for some other similarly encoded Polarimetric data I suppose. */
528 : /* -------------------------------------------------------------------- */
529 : /* IMAGE_OPT */
530 0 : TypeCode.UCharCode.Subtype1 = 63;
531 0 : TypeCode.UCharCode.Type = 192;
532 0 : TypeCode.UCharCode.Subtype2 = 18;
533 0 : TypeCode.UCharCode.Subtype3 = 18;
534 :
535 0 : record = FindCeosRecord(volume->RecordList, TypeCode, CEOS_IMAGRY_OPT_FILE,
536 : -1, -1);
537 0 : if (record == NULL)
538 0 : return 0;
539 :
540 0 : ExtractString(record, 401, 28, szSARDataFormat);
541 0 : if (!STARTS_WITH_CI(szSARDataFormat, "COMPRESSED CROSS-PRODUCTS"))
542 0 : return 0;
543 :
544 : /* -------------------------------------------------------------------- */
545 : /* Apply normal handling... */
546 : /* -------------------------------------------------------------------- */
547 0 : CeosDefaultRecipe(volume, token);
548 :
549 : /* -------------------------------------------------------------------- */
550 : /* Make sure this looks like the SIRC product we are expecting. */
551 : /* -------------------------------------------------------------------- */
552 0 : if (ImageDesc->BytesPerPixel != 10)
553 0 : return 0;
554 :
555 : /* -------------------------------------------------------------------- */
556 : /* Then fix up a few values. */
557 : /* -------------------------------------------------------------------- */
558 : /* It seems the bytes of pixel data per record is just wrong. Fix. */
559 0 : ImageDesc->PixelDataBytesPerRecord =
560 0 : ImageDesc->BytesPerPixel * ImageDesc->PixelsPerLine;
561 :
562 0 : ImageDesc->DataType = CEOS_TYP_CCP_COMPLEX_FLOAT;
563 :
564 : /* -------------------------------------------------------------------- */
565 : /* Sanity checking */
566 : /* -------------------------------------------------------------------- */
567 0 : if (ImageDesc->PixelsPerLine == 0 || ImageDesc->Lines == 0 ||
568 0 : ImageDesc->RecordsPerLine == 0 || ImageDesc->ImageDataStart == 0 ||
569 0 : ImageDesc->FileDescriptorLength == 0 || ImageDesc->DataType == 0 ||
570 0 : ImageDesc->NumChannels == 0 || ImageDesc->BytesPerPixel == 0 ||
571 0 : ImageDesc->ChannelInterleaving == 0 || ImageDesc->BytesPerRecord == 0)
572 : {
573 0 : return 0;
574 : }
575 : else
576 : {
577 0 : ImageDesc->ImageDescValid = TRUE;
578 0 : return 1;
579 : }
580 : }
581 :
582 4 : static int PALSARRecipeFCN(CeosSARVolume_t *volume, const void *token)
583 : {
584 4 : struct CeosSARImageDesc *ImageDesc = &(volume->ImageDesc);
585 4 : CeosTypeCode_t TypeCode = {0};
586 : CeosRecord_t *record;
587 : char szSARDataFormat[29], szProduct[32];
588 :
589 4 : memset(ImageDesc, 0, sizeof(struct CeosSARImageDesc));
590 :
591 : /* -------------------------------------------------------------------- */
592 : /* First, we need to check if the "SAR Data Format Type */
593 : /* identifier" is set to "COMPRESSED CROSS-PRODUCTS" which is */
594 : /* pretty idiosyncratic to SIRC products. It might also appear */
595 : /* for some other similarly encoded Polarimetric data I suppose. */
596 : /* -------------------------------------------------------------------- */
597 : /* IMAGE_OPT */
598 4 : TypeCode.UCharCode.Subtype1 = 63;
599 4 : TypeCode.UCharCode.Type = 192;
600 4 : TypeCode.UCharCode.Subtype2 = 18;
601 4 : TypeCode.UCharCode.Subtype3 = 18;
602 :
603 4 : record = FindCeosRecord(volume->RecordList, TypeCode, CEOS_IMAGRY_OPT_FILE,
604 : -1, -1);
605 4 : if (record == NULL)
606 0 : return 0;
607 :
608 4 : ExtractString(record, 401, 28, szSARDataFormat);
609 4 : if (!STARTS_WITH_CI(szSARDataFormat, "INTEGER*18 "))
610 4 : return 0;
611 :
612 0 : ExtractString(record, 49, 16, szProduct);
613 0 : if (!STARTS_WITH_CI(szProduct, "ALOS-"))
614 0 : return 0;
615 :
616 : /* -------------------------------------------------------------------- */
617 : /* Apply normal handling... */
618 : /* -------------------------------------------------------------------- */
619 0 : CeosDefaultRecipe(volume, token);
620 :
621 : /* -------------------------------------------------------------------- */
622 : /* Make sure this looks like the SIRC product we are expecting. */
623 : /* -------------------------------------------------------------------- */
624 0 : if (ImageDesc->BytesPerPixel != 18)
625 0 : return 0;
626 :
627 : /* -------------------------------------------------------------------- */
628 : /* Then fix up a few values. */
629 : /* -------------------------------------------------------------------- */
630 0 : ImageDesc->DataType = CEOS_TYP_PALSAR_COMPLEX_SHORT;
631 0 : ImageDesc->NumChannels = 6;
632 :
633 : /* -------------------------------------------------------------------- */
634 : /* Sanity checking */
635 : /* -------------------------------------------------------------------- */
636 0 : if (ImageDesc->PixelsPerLine == 0 || ImageDesc->Lines == 0 ||
637 0 : ImageDesc->RecordsPerLine == 0 || ImageDesc->ImageDataStart == 0 ||
638 0 : ImageDesc->FileDescriptorLength == 0 || ImageDesc->DataType == 0 ||
639 0 : ImageDesc->NumChannels == 0 || ImageDesc->BytesPerPixel == 0 ||
640 0 : ImageDesc->ChannelInterleaving == 0 || ImageDesc->BytesPerRecord == 0)
641 : {
642 0 : return 0;
643 : }
644 : else
645 : {
646 0 : ImageDesc->ImageDescValid = TRUE;
647 0 : return 1;
648 : }
649 : }
650 :
651 4 : void GetCeosSARImageDesc(CeosSARVolume_t *volume)
652 : {
653 : Link_t *l_link;
654 : RecipeFunctionData_t *rec_data;
655 : int (*function)(CeosSARVolume_t *volume, const void *token);
656 :
657 4 : if (RecipeFunctions == NULL)
658 : {
659 2 : RegisterRecipes();
660 : }
661 :
662 4 : if (RecipeFunctions == NULL)
663 : {
664 0 : return;
665 : }
666 :
667 12 : for (l_link = RecipeFunctions; l_link != NULL; l_link = l_link->next)
668 : {
669 12 : if (l_link->object)
670 : {
671 12 : rec_data = l_link->object;
672 12 : function = rec_data->function;
673 12 : if ((*function)(volume, rec_data->token))
674 : {
675 4 : CPLDebug("CEOS", "Using recipe '%s'.", rec_data->name);
676 4 : return;
677 : }
678 : }
679 : }
680 :
681 0 : return;
682 : }
683 :
684 52 : static void ExtractInt(CeosRecord_t *record, int type, unsigned int offset,
685 : unsigned int length, int *value)
686 : {
687 : void *buffer;
688 : char format[32];
689 :
690 52 : buffer = HMalloc(length + 1);
691 :
692 52 : switch (type)
693 : {
694 0 : case CEOS_REC_TYP_A:
695 0 : snprintf(format, sizeof(format), "A%u", length);
696 0 : GetCeosField(record, offset, format, buffer);
697 0 : *value = atoi(buffer);
698 0 : break;
699 12 : case CEOS_REC_TYP_B:
700 12 : snprintf(format, sizeof(format), "B%u", length);
701 : #ifdef notdef
702 : GetCeosField(record, offset, format, buffer);
703 : if (length <= 4)
704 : CeosToNative(value, buffer, length, length);
705 : else
706 : *value = 0;
707 : #else
708 12 : GetCeosField(record, offset, format, value);
709 : #endif
710 12 : break;
711 40 : case CEOS_REC_TYP_I:
712 40 : snprintf(format, sizeof(format), "I%u", length);
713 40 : GetCeosField(record, offset, format, value);
714 40 : break;
715 : }
716 :
717 52 : HFree(buffer);
718 52 : }
719 :
720 12 : static char *ExtractString(CeosRecord_t *record, unsigned int offset,
721 : unsigned int length, char *string)
722 : {
723 : char format[12];
724 :
725 12 : if (string == NULL)
726 : {
727 0 : string = HMalloc(length + 1);
728 : }
729 :
730 12 : snprintf(format, sizeof(format), "A%u", length);
731 :
732 12 : GetCeosField(record, offset, format, string);
733 :
734 12 : return string;
735 : }
736 :
737 8 : static int GetCeosStringType(const CeosStringType_t *CeosStringType,
738 : const char *string)
739 : {
740 : int i;
741 :
742 10 : for (i = 0; CeosStringType[i].String != NULL; i++)
743 : {
744 10 : if (strncmp(CeosStringType[i].String, string,
745 10 : strlen(CeosStringType[i].String)) == 0)
746 : {
747 8 : return CeosStringType[i].Type;
748 : }
749 : }
750 :
751 0 : return 0;
752 : }
|